Merge branch 'master' into ab-upgrade-otp-version

pull/2402/head
Ayrat Badykov 5 years ago committed by GitHub
commit 7edef009fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      CHANGELOG.md
  2. 3
      apps/block_scout_web/assets/css/app.scss
  3. 6
      apps/block_scout_web/assets/css/components/_navbar.scss
  4. 37
      apps/block_scout_web/assets/css/components/_stakes_table.scss
  5. 49
      apps/block_scout_web/assets/css/components/_tile.scss
  6. 3
      apps/block_scout_web/assets/css/theme/_base_variables.scss
  7. 5
      apps/block_scout_web/assets/css/theme/_dai_variables.scss
  8. 470
      apps/block_scout_web/assets/css/theme/_dark-theme.scss
  9. 5
      apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
  10. 14
      apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
  11. 5
      apps/block_scout_web/assets/css/theme/_goerli_variables.scss
  12. 5
      apps/block_scout_web/assets/css/theme/_kovan_variables.scss
  13. 17
      apps/block_scout_web/assets/css/theme/_lukso_variables.scss
  14. 5
      apps/block_scout_web/assets/css/theme/_neutral_variables.scss
  15. 5
      apps/block_scout_web/assets/css/theme/_poa_variables.scss
  16. 5
      apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
  17. 5
      apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
  18. 5
      apps/block_scout_web/assets/css/theme/_rsk_variables.scss
  19. 5
      apps/block_scout_web/assets/css/theme/_sokol_variables.scss
  20. 1
      apps/block_scout_web/assets/js/app.js
  21. 25
      apps/block_scout_web/assets/js/lib/market_history_chart.js
  22. 13
      apps/block_scout_web/assets/js/lib/utils.js
  23. 10
      apps/block_scout_web/assets/js/pages/chain.js
  24. 11
      apps/block_scout_web/assets/js/pages/dark-mode-switcher.js
  25. 12
      apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex
  26. 12
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex
  27. 10
      apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
  28. 12
      apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
  29. 31
      apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
  30. 5
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
  31. 2
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
  32. 21
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller.ex
  33. 11
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
  34. 21
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex
  35. 4
      apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
  36. 14
      apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
  37. 6
      apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
  38. 6
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
  39. 8
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex
  40. 6
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex
  41. 2
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex
  42. 9
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex
  43. 2
      apps/block_scout_web/lib/block_scout_web/router.ex
  44. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
  45. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
  46. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
  47. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
  48. 18
      apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
  49. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex
  50. 70
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
  51. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
  52. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
  53. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex
  54. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
  55. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex
  56. 4
      apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex
  57. 4
      apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
  58. 167
      apps/block_scout_web/lib/block_scout_web/templates/chain/_block.html.eex
  59. 12
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  60. 85
      apps/block_scout_web/lib/block_scout_web/templates/common_components/_table-loader.html.eex
  61. 72
      apps/block_scout_web/lib/block_scout_web/templates/common_components/_tile-loader.html.eex
  62. 35
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  63. 5
      apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
  64. 9
      apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
  65. 4
      apps/block_scout_web/lib/block_scout_web/templates/tokens/holder/index.html.eex
  66. 4
      apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex
  67. 4
      apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex
  68. 8
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
  69. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
  70. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
  71. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
  72. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
  73. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
  74. 38
      apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
  75. 6
      apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
  76. 1
      apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
  77. 2
      apps/block_scout_web/mix.exs
  78. 246
      apps/block_scout_web/priv/gettext/default.pot
  79. 243
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  80. 12
      apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
  81. 46
      apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
  82. 12
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
  83. 6
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
  84. 4
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex
  85. 2
      apps/ethereum_jsonrpc/mix.exs
  86. 40
      apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
  87. 10
      apps/ethereum_jsonrpc/test/ethereum_jsonrpc/transaction_test.exs
  88. 18
      apps/explorer/config/config.exs
  89. 325
      apps/explorer/lib/explorer/chain.ex
  90. 6
      apps/explorer/lib/explorer/chain/internal_transaction.ex
  91. 15
      apps/explorer/lib/explorer/chain/internal_transaction/type.ex
  92. 2
      apps/explorer/lib/explorer/counters/average_block_time.ex
  93. 2
      apps/explorer/lib/explorer/market/market_history_cache.ex
  94. 82
      apps/explorer/lib/explorer/smart_contract/reader.ex
  95. 2
      apps/explorer/mix.exs
  96. 92
      apps/explorer/test/explorer/chain_test.exs
  97. 2
      apps/explorer/test/explorer/smart_contract/reader_test.exs
  98. 8
      rel/commands/clear_build.sh

@ -1,16 +1,41 @@
## Current ## Current
### Features ### Features
- [#2366](https://github.com/poanetwork/blockscout/pull/2366) - paginate eth logs
### Fixes
- [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB
### Chore
- [#2402](https://github.com/poanetwork/blockscout/pull/2402) - bump otp version to 22.0
- [#2450](https://github.com/poanetwork/blockscout/pull/2450) - Fix clearance of logs and node_modules folders in clearing script
- [#2434](https://github.com/poanetwork/blockscout/pull/2434) - get rid of timex warnings
## 2.0.2-beta
### Features
- [#2412](https://github.com/poanetwork/blockscout/pull/2412) - dark theme
- [#2399](https://github.com/poanetwork/blockscout/pull/2399) - decode verified smart contract's logs
- [#2391](https://github.com/poanetwork/blockscout/pull/2391) - Controllers Improvements
- [#2379](https://github.com/poanetwork/blockscout/pull/2379) - Disable network selector when is empty - [#2379](https://github.com/poanetwork/blockscout/pull/2379) - Disable network selector when is empty
- [#2374](https://github.com/poanetwork/blockscout/pull/2374) - decode constructor arguments for verified smart contracts
- [#2366](https://github.com/poanetwork/blockscout/pull/2366) - paginate eth logs
- [#2360](https://github.com/poanetwork/blockscout/pull/2360) - add default evm version to smart contract verification - [#2360](https://github.com/poanetwork/blockscout/pull/2360) - add default evm version to smart contract verification
- [#2352](https://github.com/poanetwork/blockscout/pull/2352) - Fetch rewards in parallel with transactions - [#2352](https://github.com/poanetwork/blockscout/pull/2352) - Fetch rewards in parallel with transactions
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint - [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
- [#2324](https://github.com/poanetwork/blockscout/pull/2324) - set timeout for loading message on the main page
### Fixes ### Fixes
- [#2421](https://github.com/poanetwork/blockscout/pull/2421) - Fix hiding of loader for txs on the main page
- [#2420](https://github.com/poanetwork/blockscout/pull/2420) - fetch data from cache in healthy endpoint
- [#2416](https://github.com/poanetwork/blockscout/pull/2416) - Fix "page not found" handling in the router
- [#2413](https://github.com/poanetwork/blockscout/pull/2413) - remove outer tables for decoded data
- [#2410](https://github.com/poanetwork/blockscout/pull/2410) - preload smart contract for logs decoding
- [#2405](https://github.com/poanetwork/blockscout/pull/2405) - added templates for table loader and tile loader
- [#2398](https://github.com/poanetwork/blockscout/pull/2398) - show only one decoded candidate - [#2398](https://github.com/poanetwork/blockscout/pull/2398) - show only one decoded candidate
- [#2395](https://github.com/poanetwork/blockscout/pull/2395) - new block loading animation
- [#2389](https://github.com/poanetwork/blockscout/pull/2389) - Reduce Lodash lib size (86% of lib methods are not used) - [#2389](https://github.com/poanetwork/blockscout/pull/2389) - Reduce Lodash lib size (86% of lib methods are not used)
- [#2388](https://github.com/poanetwork/blockscout/pull/2388) - add create2 support to geth's js tracer
- [#2387](https://github.com/poanetwork/blockscout/pull/2387) - fix not existing keys in transaction json rpc
- [#2378](https://github.com/poanetwork/blockscout/pull/2378) - Page performance: exclude moment.js localization files except EN, remove unused css - [#2378](https://github.com/poanetwork/blockscout/pull/2378) - Page performance: exclude moment.js localization files except EN, remove unused css
- [#2368](https://github.com/poanetwork/blockscout/pull/2368) - add two columns of smart contract info - [#2368](https://github.com/poanetwork/blockscout/pull/2368) - add two columns of smart contract info
- [#2375](https://github.com/poanetwork/blockscout/pull/2375) - Update created_contract_code_indexed_at on transaction import conflict - [#2375](https://github.com/poanetwork/blockscout/pull/2375) - Update created_contract_code_indexed_at on transaction import conflict
@ -28,7 +53,9 @@
- [#2326](https://github.com/poanetwork/blockscout/pull/2326) - fix nested constructor arguments - [#2326](https://github.com/poanetwork/blockscout/pull/2326) - fix nested constructor arguments
### Chore ### Chore
- [#2402](https://github.com/poanetwork/blockscout/pull/2402) - bump otp version to 22.0 - [#2422](https://github.com/poanetwork/blockscout/pull/2422) - check if address_id is binary in token_transfers_csv endpoint
- [#2418](https://github.com/poanetwork/blockscout/pull/2418) - Remove parentheses in market cap percentage
- [#2401](https://github.com/poanetwork/blockscout/pull/2401) - add ENV vars to manage updating period of average block time and market history cache
- [#2363](https://github.com/poanetwork/blockscout/pull/2363) - add parameters example for eth rpc - [#2363](https://github.com/poanetwork/blockscout/pull/2363) - add parameters example for eth rpc
- [#2342](https://github.com/poanetwork/blockscout/pull/2342) - Upgrade Postgres image version in Docker setup - [#2342](https://github.com/poanetwork/blockscout/pull/2342) - Upgrade Postgres image version in Docker setup
- [#2325](https://github.com/poanetwork/blockscout/pull/2325) - Reduce function input to address' hash only where possible - [#2325](https://github.com/poanetwork/blockscout/pull/2325) - Reduce function input to address' hash only where possible

@ -128,6 +128,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/new_smart_contract"; @import "components/new_smart_contract";
@import "components/radio_big"; @import "components/radio_big";
@import "components/btn_no_border"; @import "components/btn_no_border";
@import "theme/dark-theme";
:export { :export {
dashboardBannerChartAxisFontColor: $dashboard-banner-chart-axis-font-color; dashboardBannerChartAxisFontColor: $dashboard-banner-chart-axis-font-color;
@ -135,4 +136,6 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
dashboardLineColorPrice: $dashboard-line-color-price; dashboardLineColorPrice: $dashboard-line-color-price;
primary: $primary; primary: $primary;
secondary: $secondary; secondary: $secondary;
darkprimary: $dark-primary;
darksecondary: $dark-secondary;
} }

@ -253,3 +253,9 @@ $navbar-logo-width: auto !default;
padding-right: 0; padding-right: 0;
} }
} }
.nav-item-networks {
.topnav-nav-link {
transition: none !important;
}
}

@ -26,6 +26,43 @@ $stakes-table-cell-separation: 25px !default;
} }
} }
// Loader
.table-content-loader {
display: inline-block;
height: 24px;
width: 100%;
border-radius: 4px;
background-color: #f5f6fa;
overflow: hidden;
position: relative;
&:before {
width: inherit;
height: inherit;
content: '';
position: absolute;
background: linear-gradient(to right, #f5f6fa 2%, #eee 18%, #f5f6fa 33%);
animation-duration: 1.7s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-name: placeholderAnimate;
background-size: 1300px;
}
}
@keyframes placeholderAnimate {
0%{ background-position: -650px 0; }
100% { background-position: 650px 0; }
}
.table-content-pseudo {
td {
&:last-child {
padding-right: 24px !important;
}
}
}
.stakes-table { .stakes-table {
min-width: fit-content; min-width: fit-content;
width: 100%; width: 100%;

@ -340,6 +340,9 @@ $tile-body-a-color: #5959d8 !default;
padding-right: 6px; padding-right: 6px;
} }
} }
.tile-type-block {
overflow: hidden;
}
.row { .row {
@include media-breakpoint-down(lg) { @include media-breakpoint-down(lg) {
margin-left: -6px; margin-left: -6px;
@ -349,6 +352,52 @@ $tile-body-a-color: #5959d8 !default;
} }
} }
// Loader
.tile-type-loading {
background-color: #fff;
padding-top: 30px;
padding-bottom: 28px;
}
.tile-loader {
display: inline-block;
height: 20px;
width: 100%;
border-radius: 4px;
background-color: #f5f6fa;
overflow: hidden;
position: relative;
&:before {
width: inherit;
height: inherit;
content: '';
position: absolute;
background: linear-gradient(to right, #f5f6fa 2%, #eee 18%, #f5f6fa 33%);
animation-duration: 1.7s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-name: tilePlaceholderAnimate;
background-size: 1300px;
}
}
.tile-label-loader {
height: 14px;
width: 80px;
}
.tile-address-loader {
& + .tile-address-loader {
margin-top: 6px;
}
}
@keyframes tilePlaceholderAnimate {
0%{ background-position: -650px 0; }
100% { background-position: 650px 0; }
}
// Loading Animation // Loading Animation
@keyframes playBlockLoadingAnimation { @keyframes playBlockLoadingAnimation {

@ -70,7 +70,10 @@ $colors: map-merge(
); );
$primary: $indigo !default; $primary: $indigo !default;
$dark-primary: #9b62ff !default;
$dark-primary-alternate: #9b62ff !default;
$secondary: #7dd79f !default; $secondary: #7dd79f !default;
$dark-secondary: #87e1a9 !default;
$tertiary: $purple !default; $tertiary: $purple !default;
$success: $green !default; $success: $green !default;
$info: $cyan !default; $info: $cyan !default;

@ -63,3 +63,8 @@ $card-tab-active: $secondary;
$badge-neutral-color: #20446e; $badge-neutral-color: #20446e;
$badge-neutral-background-color: rgba(#20446e, .1); $badge-neutral-background-color: rgba(#20446e, .1);
$api-text-monospace-color: #20446e; $api-text-monospace-color: #20446e;
// Dark theme
$dark-primary: #15bba6;
$dark-secondary: #93d7ff;
$dark-primary-alternate: #15bba6;

@ -0,0 +1,470 @@
$body-dark: #1c1d31; // body background
$dark-bg: #22223a; // hero shade
$dark-light-bg: #282945; // pills bg shade
$dark-light: #313355; // tile light top share
$labels-dark: #8a8dba; // header nav, labels
// Switcher
.dark-mode-changer {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: transparent;
border: none;
cursor: pointer;
margin-right: 5px;
outline: none !important;
box-shadow: none !important;
transition: .2s ease-in;
&:hover {
opacity: .8;
}
svg path {
fill: #828ba0;
}
&--dark {
svg path {
fill: $dark-primary;
}
}
}
.dark-theme-applied {
color: #fff;
// navbar
.navbar.navbar-primary {
background-color: $dark-light-bg;
}
.navbar-brand .navbar-logo {
filter: brightness(0) invert(1);
}
.navbar.navbar-primary .navbar-nav .nav-link {
color: $labels-dark;
.nav-link-icon {
svg path {
fill: $labels-dark;
}
}
&.active, &:hover {
.nav-link-icon {
svg path {
fill: $dark-primary;
}
}
&:before {
background-color: $dark-primary;
}
}
}
.navbar.navbar-primary .form-control {
background-color: $dark-bg;
border-color: $dark-bg;
color: #fff;
&::placeholder {
color: $labels-dark;
}
}
.navbar.navbar-primary .navbar-toggler .navbar-toggler-icon {
filter: invert(1);
}
// footer
.footer {
background: $dark-light-bg;
color: $labels-dark;
}
.footer-social-icon,
.footer-link {
color: $labels-dark;
}
.footer-social-icon:hover,
.footer-link:hover {
color: #fff;
}
.footer-list ul li::before {
background-color: $dark-secondary;
}
// hero stats
.layout-container .dashboard-banner-container {
background-image: none;
background-color: $dark-bg;
}
.dashboard-banner-network-plain-container,
.dashboard-banner-network-plain-container::after {
background-color: $dark-light-bg;
}
.dashboard-banner-network-stats-label,
.dashboard-banner-chart-legend .dashboard-banner-chart-legend-label {
color: $labels-dark;
}
.dashboard-banner-chart-legend .dashboard-banner-chart-legend-item:nth-child(1)::before {
background-color: $dark-primary;
}
.dashboard-banner-network-stats-item::before {
background-color: $dark-secondary;
}
.dashboard-banner-chart-legend .dashboard-banner-chart-legend-item:nth-child(2)::before {
background-color: $dark-secondary;
}
// main container, layout, cards
.layout-container main {
background-color: $body-dark;
}
.card {
background-color: $dark-light-bg;
box-shadow: 0 0 30px 0 rgba(23, 24, 41, 0.5);
}
.card-header {
border-bottom-color: darken($labels-dark, 30);
}
.address-detail-hash-title {
color: #fff;
}
.card-tabs {
border-bottom-color: darken($labels-dark, 30);
}
.card-tab {
background-color: transparent;
&:hover:not(.active) {
background-color: rgba($dark-primary, .15);
color: $dark-primary;
}
&.active {
background-color: $dark-primary-alternate;
color: #fff;
}
}
.card-background-1 {
background-color: $dark-primary-alternate;
}
// Components
a {
color: $dark-primary;
}
.tile {
border-top-color: $dark-light;
border-bottom-color: $dark-light;
border-right-color: $dark-light;
background-color: $dark-light;
color: $labels-dark;
&:not([class^="tile tile-type"]) {
border-left-color: $dark-light;
}
&.tile-type-coin-balance {
border-left-color: $dark-light;
}
.tile-title {
color: #fff;
}
.tile-transaction-type-block {
background-color: transparent;
}
}
.tile-bottom-contents {
background-color: $dark-bg;
}
a.tile-title {
color: #fff !important;
}
.tile.tile-type-block .tile-transaction-type-block a {
color: #fff;
}
.fade-up-blocks-chain .tile-type-block-animation {
background-color: $dark-light;
border-top-color: $dark-light;
border-right-color: $dark-light;
border-bottom-color: $dark-light;
}
.fade-up-blocks-chain .tile-type-block-animation:after {
background-color: $dark-light;
}
.cube-animation-title {
color: $labels-dark;
}
.tile .tile-body a,
.tile span[data-address-hash] { color: $dark-primary; }
.fade-up-blocks-chain .tile-type-block-animation .tile-type-line-up {
background-color: $dark-primary;
}
.tile.tile-type-block {
border-left-color: $dark-primary
}
.tile.tile-type-block .tile-status-label {
color: $dark-primary;
}
.tile.tile-type-block .tile-transaction-type-block {
border-right-color: $dark-primary;
border-top-color: $dark-primary;
border-bottom-color: $dark-primary;
}
.tile .progress {
background-color: rgba(#fff, .2);
}
.tile .progress .progress-bar {
background-color: $dark-primary;
}
.tile .tile-title-lg:not([data-balance-change-sign]) {
color: $dark-primary;
}
// btns
.btn-line {
background-color: transparent;
border-color: $dark-primary;
color: $dark-primary;
&:hover {
border-color: $dark-primary;
background-color: $dark-primary;
color: #fff;
}
}
.btn-copy-icon, .btn-qr-icon {
border-color: $dark-primary;
path {
fill: $dark-primary;
}
&:hover {
background-color: $dark-primary;
path {
fill: #fff;
}
}
}
// pagination
.pagination-container .pagination .page-link {
color: $labels-dark;
border-color: $dark-light;
background-color: $dark-light;
&:not(.no-hover):hover {
color: #fff;
background-color: $dark-primary;
path {
fill: #fff;
}
}
&[disabled] {
color: $labels-dark;
border-color: $dark-light;
background-color: $dark-light;
}
}
// dropdown
.dropdown-menu {
background-color: $dark-light;
border-left-color: $dark-light;
border-right-color: $dark-light;
border-bottom-color: $dark-light;
}
.dropdown-item {
color: #fff;
&:hover {
background-color: rgba(#fff, .1);
}
}
.dropdown-item.active {
background-color: $dark-primary;
}
.btn-dropdown-line {
background-color: $dark-light;
border-color: $dark-light;
color: $labels-dark;
}
// table
.stakes-table-th {
background-color: $dark-light;
color: $labels-dark;
}
.stakes-td {
border-bottom-color: darken($labels-dark, 30);
}
.table th, .table td {
border-top-color: darken($labels-dark, 30);
}
hr {
border-top-color: darken($labels-dark, 30);
}
// api's
.api-anchors-list {
background-color: $dark-light;
}
.api-doc-list-item {
border-bottom-color: darken($labels-dark, 30);
}
.card-subtitle,
.api-anchors-list-item-title,
.api-doc-list-item-title {
color: #fff;
}
.api-text-monospace {
color: $dark-primary;
}
.api-text-monospace-background {
background-color: rgba($dark-primary, .15);
}
.badge.badge-neutral {
background-color: rgba($dark-primary, .15);
color: $dark-primary;
}
// download csv button
.download-all-transactions .download-all-transactions-link svg path {
fill: $dark-primary;
}
//tooltips
.tooltip .arrow:before {
border-top-color: $dark-primary;
border-bottom-color: $dark-primary;
}
.tooltip > .tooltip-inner {background-color: $dark-primary;}
//network select
.network-selector-overlay {
background-color: rgba($dark-bg, .9);
}
.network-selector {
background-color: $dark-light-bg;
}
.network-selector-title {
color: #fff;
}
.network-selector-text {
color: $labels-dark;
}
.network-selector-close path {
fill: #fff;
}
.network-selector-search-container {
background-color: $dark-light;
}
.network-selector-search-container path {
fill: $labels-dark;
}
.network-selector-search-input {
color: #fff !important;
&::placeholder {
color: $labels-dark;
}
}
.network-selector-tab {
color: $labels-dark;
&:hover, &.active {
color: #fff;
}
&.active {
&:after {
background-color: $dark-primary;
}
}
}
.network-selector-item,
.network-selector-tabs-container {
border-bottom-color: darken($labels-dark, 30);
}
.network-selector-item-title {
color: #fff;
}
.network-selector-item-type {
color: $labels-dark;
}
.radio .radio-icon {
border-color: $labels-dark
}
.network-selector-item-url:hover .network-selector-item-type {
color: #fff;
}
//coin dropdown
.token-balance-dropdown.dropdown-menu {
border-color: $dark-light !important;
box-shadow: 0 0 30px 0 rgba(23, 24, 41, 0.5) !important;
}
.token-balance-dropdown .dropdown-search-icon path {
fill: $labels-dark;
}
.token-balance-dropdown .dropdown-search-field {
background-color: $dark-light;
border-color: $dark-light;
color: #fff;
&::placeholder {
color: $labels-dark;
}
}
.token-balance-dropdown[aria-labelledby="dropdown-tokens"] .dropdown-items .dropdown-item:hover {
color: #fff !important;
}
.dropdown-header {
color: $labels-dark;
}
.border-bottom {
border-bottom-color: darken($labels-dark, 30) !important;
}
// coin balance history chart
.chartjs-render-monitor[data-chart="coinBalanceHistoryChart"] {
filter: brightness(0) invert(1) !important;
}
// logs search
.logs-search-input, .logs-search-btn, .logs-search-btn-cancel {
background-color: $dark-light;
border-color: $dark-light;
color: #fff;
}
.logs-search-btn {
color: $labels-dark;
}
.logs-search-btn {
&:hover {
background-color: $dark-primary;
color: #fff;
}
}
.logs-search-input {
&::placeholder {
color: $labels-dark;
}
}
// code
pre {
color: #fff;
}
// info allert
.alert-info {
color: $labels-dark;
background-color: $dark-light;
border-color: $dark-light;
}
// dark text
.text-dark {
color: #fff;
}
}

@ -75,3 +75,8 @@ $card-tab-active: $tertiary;
$badge-neutral-color: $tertiary; $badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1); $badge-neutral-background-color: rgba($tertiary, .1);
$api-text-monospace-color: $tertiary; $api-text-monospace-color: $tertiary;
// Dark theme
$dark-primary: #8588ff;
$dark-secondary: #4ad7a7;
$dark-primary-alternate: #5b5ed8;

@ -57,3 +57,17 @@ $card-tab-active: $secondary;
); );
} }
} }
// Dark theme
$dark-primary: #49a2ee;
$dark-secondary: #4ad7a7;
$dark-primary-alternate: #49a2ee;
.dark-theme-applied {
.dashboard-banner-chart-legend .dashboard-banner-chart-legend-item:nth-child(1)::before {
background-color: $dark-primary !important;
}
.dashboard-banner-chart-legend .dashboard-banner-chart-legend-item:nth-child(2)::before {
background-color: $dark-secondary !important;
}
}

@ -78,3 +78,8 @@ $card-tab-active: $sub-accent-color;
$badge-neutral-color: $sub-accent-color; $badge-neutral-color: $sub-accent-color;
$badge-neutral-background-color: rgba($sub-accent-color, .1); $badge-neutral-background-color: rgba($sub-accent-color, .1);
$api-text-monospace-color: $sub-accent-color; $api-text-monospace-color: $sub-accent-color;
// Dark theme
$dark-primary: #e1995a;
$dark-secondary: #aeaeae;
$dark-primary-alternate: #e1995a;

@ -75,3 +75,8 @@ $badge-success-background-color: rgba(#15bba6, .1);
$badge-neutral-color: $tertiary; $badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1); $badge-neutral-background-color: rgba($tertiary, .1);
$api-text-monospace-color: $tertiary; $api-text-monospace-color: $tertiary;
// Dark theme
$dark-primary: #42e2d7;
$dark-secondary: #1f857f;
$dark-primary-alternate: #1f857f;

@ -151,3 +151,20 @@ $dashboard-banner-network-plain-container-height: 150px;
$badge-neutral-color: $tertiary; $badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1); $badge-neutral-background-color: rgba($tertiary, .1);
$api-text-monospace-color: $tertiary; $api-text-monospace-color: $tertiary;
// Dark theme
$dark-primary: #fdcec4;
$dark-secondary: #a96c55;
$dark-primary-alternate: #a96c55;
.dark-theme-applied {
.dashboard-banner-network-stats-value {
color: $dark-primary !important;
}
.layout-container .dashboard-banner-container {
background-color: #282945 !important;
}
.dashboard-banner-network-plain-container::after {
box-shadow: none !important;
}
}

@ -72,3 +72,8 @@ $api-text-monospace-color: $primary;
color: $primary !important; color: $primary !important;
} }
} }
// Dark theme
$dark-primary: #9b62ff;
$dark-secondary: #87e1a9;
$dark-primary-alternate: #7e50d0;

@ -72,3 +72,8 @@ $api-text-monospace-color: $primary;
color: $primary !important; color: $primary !important;
} }
} }
// Dark theme
$dark-primary: #9b62ff;
$dark-secondary: #87e1a9;
$dark-primary-alternate: #7e50d0;

@ -57,3 +57,8 @@ $card-tab-active: $secondary;
); );
} }
} }
// Dark theme
$dark-primary: #38a9f5;
$dark-secondary: #76f1ff;
$dark-primary-alternate: #38a9f5;

@ -57,3 +57,8 @@ $card-tab-active: $secondary;
); );
} }
} }
// Dark theme
$dark-primary: #38a9f5;
$dark-secondary: #76f1ff;
$dark-primary-alternate: #38a9f5;

@ -65,3 +65,8 @@ $card-tab-active: $secondary;
// Badges // Badges
$badge-neutral-color: #1a323b; $badge-neutral-color: #1a323b;
$badge-neutral-background-color: rgba(#1a323b, .1); $badge-neutral-background-color: rgba(#1a323b, .1);
// Dark theme
$dark-primary: #38c5a4;
$dark-secondary: #e39a54;
$dark-primary-alternate: #30ab8d;

@ -73,3 +73,8 @@ $card-tab-active: $sub-accent-color;
// Badges // Badges
$badge-neutral-color: $tertiary; $badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1); $badge-neutral-background-color: rgba($tertiary, .1);
// Dark theme
$dark-primary: #40bfb2;
$dark-secondary: #25c9ff;
$dark-primary-alternate: #1c9f90;

@ -35,6 +35,7 @@ import './pages/favorites'
import './pages/network-search' import './pages/network-search'
import './pages/layout' import './pages/layout'
import './pages/verification_form' import './pages/verification_form'
import './pages/dark-mode-switcher'
import './pages/admin/tasks.js' import './pages/admin/tasks.js'

@ -4,6 +4,7 @@ import humps from 'humps'
import numeral from 'numeral' import numeral from 'numeral'
import { formatUsdValue } from '../lib/currency' import { formatUsdValue } from '../lib/currency'
import sassVariables from '../../css/app.scss' import sassVariables from '../../css/app.scss'
import { showLoader } from '../lib/utils'
const config = { const config = {
type: 'line', type: 'line',
@ -87,6 +88,17 @@ function getMarketCapData (marketHistoryData, availableSupply) {
} }
} }
// colors for light and dark theme
var priceLineColor
var mcapLineColor
if (localStorage.getItem('current-color-mode') === 'dark') {
priceLineColor = sassVariables.darkprimary
mcapLineColor = sassVariables.darksecondary
} else {
priceLineColor = sassVariables.dashboardLineColorPrice
mcapLineColor = sassVariables.dashboardLineColorMarket
}
class MarketHistoryChart { class MarketHistoryChart {
constructor (el, availableSupply, marketHistoryData) { constructor (el, availableSupply, marketHistoryData) {
this.price = { this.price = {
@ -95,8 +107,8 @@ class MarketHistoryChart {
data: getPriceData(marketHistoryData), data: getPriceData(marketHistoryData),
fill: false, fill: false,
pointRadius: 0, pointRadius: 0,
backgroundColor: sassVariables.dashboardLineColorPrice, backgroundColor: priceLineColor,
borderColor: sassVariables.dashboardLineColorPrice, borderColor: priceLineColor,
lineTension: 0 lineTension: 0
} }
this.marketCap = { this.marketCap = {
@ -105,8 +117,8 @@ class MarketHistoryChart {
data: getMarketCapData(marketHistoryData, availableSupply), data: getMarketCapData(marketHistoryData, availableSupply),
fill: false, fill: false,
pointRadius: 0, pointRadius: 0,
backgroundColor: sassVariables.dashboardLineColorMarket, backgroundColor: mcapLineColor,
borderColor: sassVariables.dashboardLineColorMarket, borderColor: mcapLineColor,
lineTension: 0 lineTension: 0
} }
this.availableSupply = availableSupply this.availableSupply = availableSupply
@ -129,6 +141,10 @@ class MarketHistoryChart {
export function createMarketHistoryChart (el) { export function createMarketHistoryChart (el) {
const dataPath = el.dataset.market_history_chart_path const dataPath = el.dataset.market_history_chart_path
const $chartLoading = $('[data-chart-loading-message]') const $chartLoading = $('[data-chart-loading-message]')
const isTimeout = true
const timeoutID = showLoader(isTimeout, $chartLoading)
const $chartError = $('[data-chart-error-message]') const $chartError = $('[data-chart-error-message]')
const chart = new MarketHistoryChart(el, 0, []) const chart = new MarketHistoryChart(el, 0, [])
$.getJSON(dataPath, {type: 'JSON'}) $.getJSON(dataPath, {type: 'JSON'})
@ -143,6 +159,7 @@ export function createMarketHistoryChart (el) {
}) })
.always(() => { .always(() => {
$chartLoading.hide() $chartLoading.hide()
clearTimeout(timeoutID)
}) })
return chart return chart
} }

@ -11,3 +11,16 @@ export function batchChannel (func) {
debouncedFunc() debouncedFunc()
} }
} }
export function showLoader (isTimeout, loader) {
if (isTimeout) {
const timeout = setTimeout(function () {
loader.removeAttr('hidden')
loader.show()
}, 1000)
return timeout
} else {
loader.hide()
return null
}
}

@ -9,7 +9,7 @@ import numeral from 'numeral'
import socket from '../socket' import socket from '../socket'
import { exchangeRateChannel, formatUsdValue } from '../lib/currency' import { exchangeRateChannel, formatUsdValue } from '../lib/currency'
import { createStore, connectElements } from '../lib/redux_helpers.js' import { createStore, connectElements } from '../lib/redux_helpers.js'
import { batchChannel } from '../lib/utils' import { batchChannel, showLoader } from '../lib/utils'
import listMorph from '../lib/list_morph' import listMorph from '../lib/list_morph'
import { createMarketHistoryChart } from '../lib/market_history_chart' import { createMarketHistoryChart } from '../lib/market_history_chart'
@ -214,11 +214,7 @@ const elements = {
}, },
'[data-selector="chain-block-list"] [data-selector="loading-message"]': { '[data-selector="chain-block-list"] [data-selector="loading-message"]': {
render ($el, state, oldState) { render ($el, state, oldState) {
if (state.blocksLoading) { showLoader(state.blocksLoading, $el)
$el.show()
} else {
$el.hide()
}
} }
}, },
'[data-selector="transactions-list"] [data-selector="error-message"]': { '[data-selector="transactions-list"] [data-selector="error-message"]': {
@ -228,7 +224,7 @@ const elements = {
}, },
'[data-selector="transactions-list"] [data-selector="loading-message"]': { '[data-selector="transactions-list"] [data-selector="loading-message"]': {
render ($el, state, oldState) { render ($el, state, oldState) {
$el.toggle(state.transactionsLoading) showLoader(state.transactionsLoading, $el)
} }
}, },
'[data-selector="transactions-list"]': { '[data-selector="transactions-list"]': {

@ -0,0 +1,11 @@
import $ from 'jquery'
$('.dark-mode-changer').click(function () {
if (localStorage.getItem('current-color-mode') === 'dark') {
localStorage.setItem('current-color-mode', 'light')
} else {
localStorage.setItem('current-color-mode', 'dark')
}
// reload each theme switch
document.location.reload(true)
})

@ -16,7 +16,7 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash, [], false) do :ok <- Chain.check_address_exists(address_hash) do
full_options = paging_options(params) full_options = paging_options(params)
coin_balances_plus_one = Chain.address_to_coin_balances(address_hash, full_options) coin_balances_plus_one = Chain.address_to_coin_balances(address_hash, full_options)
@ -32,7 +32,7 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
address_coin_balance_path( address_coin_balance_path(
conn, conn,
:index, :index,
address, address_hash,
Map.delete(next_page_params, "type") Map.delete(next_page_params, "type")
) )
end end
@ -52,7 +52,7 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
:error -> :error ->
unprocessable_entity(conn) unprocessable_entity(conn)
{:error, :not_found} -> :not_found ->
not_found(conn) not_found(conn)
end end
end end
@ -68,6 +68,12 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
validation_count: validation_count(address_hash), validation_count: validation_count(address_hash),
current_path: current_path(conn) current_path: current_path(conn)
) )
else
:error ->
unprocessable_entity(conn)
{:error, :not_found} ->
not_found(conn)
end end
end end
end end

@ -8,8 +8,18 @@ defmodule BlockScoutWeb.AddressContractController do
alias Indexer.Fetcher.CoinBalanceOnDemand alias Indexer.Fetcher.CoinBalanceOnDemand
def index(conn, %{"address_id" => address_hash_string}) do def index(conn, %{"address_id" => address_hash_string}) do
address_options = [
necessity_by_association: %{
:contracts_creation_internal_transaction => :optional,
:names => :optional,
:smart_contract => :optional,
:token => :optional,
:contracts_creation_transaction => :optional
}
]
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.find_contract_address(address_hash) do {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true) do
render( render(
conn, conn,
"index.html", "index.html",

@ -16,7 +16,7 @@ defmodule BlockScoutWeb.AddressLogsController do
def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash, [], false) do :ok <- Chain.check_address_exists(address_hash) do
logs_plus_one = Chain.address_to_logs(address_hash, paging_options(params)) logs_plus_one = Chain.address_to_logs(address_hash, paging_options(params))
{results, next_page} = split_list_by_page(logs_plus_one) {results, next_page} = split_list_by_page(logs_plus_one)
@ -26,7 +26,7 @@ defmodule BlockScoutWeb.AddressLogsController do
nil nil
next_page_params -> next_page_params ->
address_logs_path(conn, :index, address, Map.delete(next_page_params, "type")) address_logs_path(conn, :index, address_hash, Map.delete(next_page_params, "type"))
end end
items = items =
@ -74,7 +74,7 @@ defmodule BlockScoutWeb.AddressLogsController do
def search_logs(conn, %{"topic" => topic, "address_id" => address_hash_string} = params) do def search_logs(conn, %{"topic" => topic, "address_id" => address_hash_string} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash, [], false) do :ok <- Chain.check_address_exists(address_hash) do
topic = String.trim(topic) topic = String.trim(topic)
formatted_topic = if String.starts_with?(topic, "0x"), do: topic, else: "0x" <> topic formatted_topic = if String.starts_with?(topic, "0x"), do: topic, else: "0x" <> topic
@ -89,7 +89,7 @@ defmodule BlockScoutWeb.AddressLogsController do
nil nil
next_page_params -> next_page_params ->
address_logs_path(conn, :index, address, Map.delete(next_page_params, "type")) address_logs_path(conn, :index, address_hash, Map.delete(next_page_params, "type"))
end end
items = items =
@ -115,4 +115,6 @@ defmodule BlockScoutWeb.AddressLogsController do
not_found(conn) not_found(conn)
end end
end end
def search_logs(conn, _), do: not_found(conn)
end end

@ -15,8 +15,18 @@ defmodule BlockScoutWeb.AddressReadContractController do
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
def index(conn, %{"address_id" => address_hash_string}) do def index(conn, %{"address_id" => address_hash_string}) do
address_options = [
necessity_by_association: %{
:contracts_creation_internal_transaction => :optional,
:names => :optional,
:smart_contract => :optional,
:token => :optional,
:contracts_creation_transaction => :optional
}
]
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.find_contract_address(address_hash) do {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true) do
render( render(
conn, conn,
"index.html", "index.html",

@ -83,7 +83,11 @@ defmodule BlockScoutWeb.AddressTransactionController do
unprocessable_entity(conn) unprocessable_entity(conn)
{:error, :not_found} -> {:error, :not_found} ->
not_found(conn) with {:ok, _} <- Chain.Hash.Address.validate(address_hash_string) do
json(conn, %{items: [], next_page_path: ""})
else
{:error, _} -> not_found(conn)
end
end end
end end
@ -106,11 +110,28 @@ defmodule BlockScoutWeb.AddressTransactionController do
unprocessable_entity(conn) unprocessable_entity(conn)
{:error, :not_found} -> {:error, :not_found} ->
not_found(conn) {:ok, address_hash} = Chain.string_to_address_hash(address_hash_string)
address = %Chain.Address{hash: address_hash, smart_contract: nil, token: nil}
with {:ok, _} <- Chain.Hash.Address.validate(address_hash_string) do
render(
conn,
"index.html",
address: address,
coin_balance_status: nil,
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
filter: params["filter"],
transaction_count: 0,
validation_count: 0,
current_path: current_path(conn)
)
else
{:error, _} -> not_found(conn)
end
end end
end end
def token_transfers_csv(conn, %{"address_id" => address_hash_string}) do def token_transfers_csv(conn, %{"address_id" => address_hash_string}) when is_binary(address_hash_string) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do {:ok, address} <- Chain.hash_to_address(address_hash) do
address address
@ -130,6 +151,8 @@ defmodule BlockScoutWeb.AddressTransactionController do
end end
end end
def token_transfers_csv(conn, _), do: not_found(conn)
def transactions_csv(conn, %{"address_id" => address_hash_string}) do def transactions_csv(conn, %{"address_id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do {:ok, address} <- Chain.hash_to_address(address_hash) do
@ -149,4 +172,6 @@ defmodule BlockScoutWeb.AddressTransactionController do
not_found(conn) not_found(conn)
end end
end end
def transactions_csv(conn, _), do: not_found(conn)
end end

@ -8,9 +8,8 @@ defmodule BlockScoutWeb.API.RPC.BlockController do
def getblockreward(conn, params) do def getblockreward(conn, params) do
with {:block_param, {:ok, unsafe_block_number}} <- {:block_param, Map.fetch(params, "blockno")}, with {:block_param, {:ok, unsafe_block_number}} <- {:block_param, Map.fetch(params, "blockno")},
{:ok, block_number} <- ChainWeb.param_to_block_number(unsafe_block_number), {:ok, block_number} <- ChainWeb.param_to_block_number(unsafe_block_number),
block_options = [necessity_by_association: %{transactions: :optional}], {:ok, block} <- Chain.number_to_block(block_number) do
{:ok, block} <- Chain.number_to_block(block_number, block_options) do reward = Chain.block_reward(block_number)
reward = Chain.block_reward(block)
render(conn, :block_reward, block: block, reward: reward) render(conn, :block_reward, block: block, reward: reward)
else else

@ -10,7 +10,7 @@ defmodule BlockScoutWeb.API.RPC.TransactionController do
{:format, {:ok, transaction_hash}} <- to_transaction_hash(txhash_param), {:format, {:ok, transaction_hash}} <- to_transaction_hash(txhash_param),
{:transaction, {:ok, transaction}} <- transaction_from_hash(transaction_hash), {:transaction, {:ok, transaction}} <- transaction_from_hash(transaction_hash),
paging_options <- paging_options(params) do paging_options <- paging_options(params) do
logs = Chain.transaction_to_logs(transaction, paging_options) logs = Chain.transaction_to_logs(transaction_hash, paging_options)
{logs, next_page} = split_list_by_page(logs) {logs, next_page} = split_list_by_page(logs)
render(conn, :gettxinfo, %{ render(conn, :gettxinfo, %{

@ -7,8 +7,9 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
def create(conn, params) do def create(conn, params) do
if auth_token(conn) == actual_token() do if auth_token(conn) == actual_token() do
with {:ok, hash} <- validate_address_hash(params["address_hash"]), with {:ok, hash} <- validate_address_hash(params["address_hash"]),
:ok <- smart_contract_exists?(hash), :ok <- Chain.check_address_exists(hash),
:ok <- decompiled_contract_exists?(params["address_hash"], params["decompiler_version"]) do {:contract, :not_found} <-
{:contract, Chain.check_decompiled_contract_exists(params["address_hash"], params["decompiler_version"])} do
case Chain.create_decompiled_smart_contract(params) do case Chain.create_decompiled_smart_contract(params) do
{:ok, decompiled_smart_contract} -> {:ok, decompiled_smart_contract} ->
send_resp(conn, :created, Jason.encode!(decompiled_smart_contract)) send_resp(conn, :created, Jason.encode!(decompiled_smart_contract))
@ -29,7 +30,7 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
:not_found -> :not_found ->
send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"})) send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"}))
:contract_exists -> {:contract, :ok} ->
send_resp( send_resp(
conn, conn,
:unprocessable_entity, :unprocessable_entity,
@ -41,13 +42,6 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
end end
end end
defp smart_contract_exists?(address_hash) do
case Chain.hash_to_address(address_hash) do
{:ok, _address} -> :ok
_ -> :not_found
end
end
defp validate_address_hash(address_hash) do defp validate_address_hash(address_hash) do
case Address.cast(address_hash) do case Address.cast(address_hash) do
{:ok, hash} -> {:ok, hash} {:ok, hash} -> {:ok, hash}
@ -55,13 +49,6 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
end end
end end
defp decompiled_contract_exists?(address_hash, decompiler_version) do
case Chain.decompiled_code(address_hash, decompiler_version) do
{:ok, _} -> :contract_exists
_ -> :ok
end
end
defp auth_token(conn) do defp auth_token(conn) do
case get_req_header(conn, "auth_token") do case get_req_header(conn, "auth_token") do
[token] -> token [token] -> token

@ -4,19 +4,22 @@ defmodule BlockScoutWeb.API.V1.HealthController do
alias Explorer.Chain alias Explorer.Chain
def health(conn, _) do def health(conn, _) do
with {:ok, number, timestamp} <- Chain.last_block_status() do with {:ok, number, timestamp} <- Chain.last_db_block_status(),
send_resp(conn, :ok, result(number, timestamp)) {:ok, cache_number, cache_timestamp} <- Chain.last_cache_block_status() do
send_resp(conn, :ok, result(number, timestamp, cache_number, cache_timestamp))
else else
status -> send_resp(conn, :internal_server_error, error(status)) status -> send_resp(conn, :internal_server_error, error(status))
end end
end end
def result(number, timestamp) do def result(number, timestamp, cache_number, cache_timestamp) do
%{ %{
"healthy" => true, "healthy" => true,
"data" => %{ "data" => %{
"latest_block_number" => to_string(number), "latest_block_number" => to_string(number),
"latest_block_inserted_at" => to_string(timestamp) "latest_block_inserted_at" => to_string(timestamp),
"cache_latest_block_number" => to_string(cache_number),
"cache_latest_block_inserted_at" => to_string(cache_timestamp)
} }
} }
|> Jason.encode!() |> Jason.encode!()

@ -7,8 +7,8 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
def create(conn, params) do def create(conn, params) do
with {:ok, hash} <- validate_address_hash(params["address_hash"]), with {:ok, hash} <- validate_address_hash(params["address_hash"]),
:ok <- smart_contract_exists?(hash), :ok <- Chain.check_address_exists(hash),
:ok <- verified_smart_contract_exists?(hash) do {:contract, :not_found} <- {:contract, Chain.check_verified_smart_contract_exists(hash)} do
external_libraries = fetch_external_libraries(params) external_libraries = fetch_external_libraries(params)
case Publisher.publish(hash, params, external_libraries) do case Publisher.publish(hash, params, external_libraries) do
@ -31,7 +31,7 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
:not_found -> :not_found ->
send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"})) send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"}))
:contract_exists -> {:contract, :ok} ->
send_resp( send_resp(
conn, conn,
:unprocessable_entity, :unprocessable_entity,
@ -40,13 +40,6 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
end end
end end
defp smart_contract_exists?(address_hash) do
case Chain.hash_to_address(address_hash) do
{:ok, _address} -> :ok
_ -> :not_found
end
end
defp validate_address_hash(address_hash) do defp validate_address_hash(address_hash) do
case Address.cast(address_hash) do case Address.cast(address_hash) do
{:ok, hash} -> {:ok, hash} {:ok, hash} -> {:ok, hash}
@ -54,14 +47,6 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
end end
end end
defp verified_smart_contract_exists?(address_hash) do
if Chain.address_hash_to_smart_contract(address_hash) do
:contract_exists
else
:ok
end
end
defp encode(data) do defp encode(data) do
Jason.encode!(data) Jason.encode!(data)
end end

@ -26,7 +26,7 @@ defmodule BlockScoutWeb.BlockTransactionController do
paging_options(params) paging_options(params)
) )
transactions_plus_one = Chain.block_to_transactions(block, full_options) transactions_plus_one = Chain.block_to_transactions(block.hash, full_options)
{transactions, next_page} = split_list_by_page(transactions_plus_one) {transactions, next_page} = split_list_by_page(transactions_plus_one)
@ -89,7 +89,7 @@ defmodule BlockScoutWeb.BlockTransactionController do
:rewards => :optional :rewards => :optional
} }
) do ) do
block_transaction_count = Chain.block_to_transaction_count(block) block_transaction_count = Chain.block_to_transaction_count(block.hash)
render( render(
conn, conn,

@ -2,7 +2,7 @@ defmodule BlockScoutWeb.ChainController do
use BlockScoutWeb, :controller use BlockScoutWeb, :controller
alias BlockScoutWeb.ChainView alias BlockScoutWeb.ChainView
alias Explorer.{Chain, PagingOptions, Repo} alias Explorer.{Chain, PagingOptions}
alias Explorer.Chain.{Address, Block, Transaction} alias Explorer.Chain.{Address, Block, Transaction}
alias Explorer.Chain.Supply.RSK alias Explorer.Chain.Supply.RSK
alias Explorer.Counters.AverageBlockTime alias Explorer.Counters.AverageBlockTime
@ -52,6 +52,8 @@ defmodule BlockScoutWeb.ChainController do
end end
end end
def search(conn, _), do: not_found(conn)
def token_autocomplete(conn, %{"q" => term}) when is_binary(term) do def token_autocomplete(conn, %{"q" => term}) when is_binary(term) do
if term == "" do if term == "" do
json(conn, "{}") json(conn, "{}")
@ -72,9 +74,15 @@ defmodule BlockScoutWeb.ChainController do
def chain_blocks(conn, _params) do def chain_blocks(conn, _params) do
if ajax?(conn) do if ajax?(conn) do
blocks = blocks =
[paging_options: %PagingOptions{page_size: 4}] [
paging_options: %PagingOptions{page_size: 4},
necessity_by_association: %{
[miner: :names] => :optional,
:transactions => :optional,
:rewards => :optional
}
]
|> Chain.list_blocks() |> Chain.list_blocks()
|> Repo.preload([[miner: :names], :transactions, :rewards])
|> Enum.map(fn block -> |> Enum.map(fn block ->
%{ %{
chain_block_html: chain_block_html:

@ -30,10 +30,12 @@ defmodule BlockScoutWeb.SmartContractController do
end end
end end
def index(conn, _), do: not_found(conn)
def show(conn, params) do def show(conn, params) do
with true <- ajax?(conn), with true <- ajax?(conn),
{:ok, address_hash} <- Chain.string_to_address_hash(params["id"]), {:ok, address_hash} <- Chain.string_to_address_hash(params["id"]),
{:ok, _address} <- Chain.find_contract_address(address_hash), :ok <- Chain.check_contract_address_exists(address_hash),
outputs = outputs =
Reader.query_function( Reader.query_function(
address_hash, address_hash,
@ -51,7 +53,7 @@ defmodule BlockScoutWeb.SmartContractController do
:error -> :error ->
unprocessable_entity(conn) unprocessable_entity(conn)
{:error, :not_found} -> :not_found ->
not_found(conn) not_found(conn)
_ -> _ ->

@ -62,15 +62,15 @@ defmodule BlockScoutWeb.TransactionController do
def show(conn, %{"id" => id}) do def show(conn, %{"id" => id}) do
with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(id), with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(id),
{:ok, %Chain.Transaction{} = transaction} <- Chain.hash_to_transaction(transaction_hash) do :ok <- Chain.check_transaction_exists(transaction_hash) do
if Chain.transaction_has_token_transfers?(transaction.hash) do if Chain.transaction_has_token_transfers?(transaction_hash) do
redirect(conn, to: transaction_token_transfer_path(conn, :index, id)) redirect(conn, to: transaction_token_transfer_path(conn, :index, id))
else else
redirect(conn, to: transaction_internal_transaction_path(conn, :index, id)) redirect(conn, to: transaction_internal_transaction_path(conn, :index, id))
end end
else else
:error -> conn |> put_status(422) |> render("invalid.html", transaction_hash: id) :error -> conn |> put_status(422) |> render("invalid.html", transaction_hash: id)
{:error, :not_found} -> conn |> put_status(404) |> render("not_found.html", transaction_hash: id) :not_found -> conn |> put_status(404) |> render("not_found.html", transaction_hash: id)
end end
end end
end end

@ -10,7 +10,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do
with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string),
{:ok, transaction} <- Chain.hash_to_transaction(hash) do :ok <- Chain.check_transaction_exists(hash) do
full_options = full_options =
Keyword.merge( Keyword.merge(
[ [
@ -24,7 +24,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
paging_options(params) paging_options(params)
) )
internal_transactions_plus_one = Chain.transaction_to_internal_transactions(transaction, full_options) internal_transactions_plus_one = Chain.transaction_to_internal_transactions(hash, full_options)
{internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one) {internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one)
@ -37,7 +37,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
transaction_internal_transaction_path( transaction_internal_transaction_path(
conn, conn,
:index, :index,
transaction, hash,
Map.delete(next_page_params, "type") Map.delete(next_page_params, "type")
) )
end end
@ -66,7 +66,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
|> put_view(TransactionView) |> put_view(TransactionView)
|> render("invalid.html", transaction_hash: hash_string) |> render("invalid.html", transaction_hash: hash_string)
{:error, :not_found} -> :not_found ->
conn conn
|> put_status(404) |> put_status(404)
|> put_view(TransactionView) |> put_view(TransactionView)

@ -11,7 +11,9 @@ defmodule BlockScoutWeb.TransactionLogController do
def index(conn, %{"transaction_id" => transaction_hash_string, "type" => "JSON"} = params) do def index(conn, %{"transaction_id" => transaction_hash_string, "type" => "JSON"} = params) do
with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string),
{:ok, transaction} <- {:ok, transaction} <-
Chain.hash_to_transaction(transaction_hash) do Chain.hash_to_transaction(transaction_hash,
necessity_by_association: %{[to_address: :smart_contract] => :optional}
) do
full_options = full_options =
Keyword.merge( Keyword.merge(
[ [
@ -22,7 +24,7 @@ defmodule BlockScoutWeb.TransactionLogController do
paging_options(params) paging_options(params)
) )
logs_plus_one = Chain.transaction_to_logs(transaction, full_options) logs_plus_one = Chain.transaction_to_logs(transaction_hash, full_options)
{logs, next_page} = split_list_by_page(logs_plus_one) {logs, next_page} = split_list_by_page(logs_plus_one)

@ -19,7 +19,7 @@ defmodule BlockScoutWeb.TransactionRawTraceController do
:token_transfers => :optional :token_transfers => :optional
} }
) do ) do
internal_transactions = Chain.transaction_to_internal_transactions(transaction) internal_transactions = Chain.transaction_to_internal_transactions(hash)
render( render(
conn, conn,

@ -10,8 +10,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do
with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string),
{:ok, transaction} <- :ok <- Chain.check_transaction_exists(hash) do
Chain.hash_to_transaction(hash) do
full_options = full_options =
Keyword.merge( Keyword.merge(
[ [
@ -24,7 +23,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
paging_options(params) paging_options(params)
) )
token_transfers_plus_one = Chain.transaction_to_token_transfers(transaction, full_options) token_transfers_plus_one = Chain.transaction_to_token_transfers(hash, full_options)
{token_transfers, next_page} = split_list_by_page(token_transfers_plus_one) {token_transfers, next_page} = split_list_by_page(token_transfers_plus_one)
@ -34,7 +33,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
nil nil
next_page_params -> next_page_params ->
transaction_token_transfer_path(conn, :index, transaction, Map.delete(next_page_params, "type")) transaction_token_transfer_path(conn, :index, hash, Map.delete(next_page_params, "type"))
end end
items = items =
@ -62,7 +61,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
|> put_view(TransactionView) |> put_view(TransactionView)
|> render("invalid.html", transaction_hash: hash_string) |> render("invalid.html", transaction_hash: hash_string)
{:error, :not_found} -> :not_found ->
conn conn
|> put_status(404) |> put_status(404)
|> put_view(TransactionView) |> put_view(TransactionView)

@ -261,6 +261,6 @@ defmodule BlockScoutWeb.Router do
get("/api_docs", APIDocsController, :index) get("/api_docs", APIDocsController, :index)
get("/eth_rpc_api_docs", APIDocsController, :eth_rpc) get("/eth_rpc_api_docs", APIDocsController, :eth_rpc)
get("/:page", PageNotFoundController, :index) get("/*path", PageNotFoundController, :index)
end end
end end

@ -21,7 +21,7 @@
<td class="stakes-td color-lighten"> <td class="stakes-td color-lighten">
<!-- percentage of coins from total supply --> <!-- percentage of coins from total supply -->
<%= if @total_supply do %> <%= if @total_supply do %>
(<%= balance_percentage(@address, @total_supply) %>) <%= balance_percentage(@address, @total_supply) %>
<% end %> <% end %>
</td> </td>
<td class="stakes-td"> <td class="stakes-td">

@ -38,7 +38,7 @@
</tr> </tr>
</thead> </thead>
<tbody data-items data-selector="top-addresses-list"> <tbody data-items data-selector="top-addresses-list">
<%= render BlockScoutWeb.CommonComponentsView, "_table-loader.html" %>
</tbody> </tbody>
</table> </table>
</div> </div>

@ -84,9 +84,11 @@
<%= gettext("Transactions Sent") %> <%= gettext("Transactions Sent") %>
<% end %> <% end %>
</span> </span>
<%= if @address.fetched_coin_balance_block_number do %>
<span class="address-detail-item"> <span class="address-detail-item">
<%= gettext("Last Balance Update: Block #") %><span data-selector="fetched-coin-balance-block-number"><%= @address.fetched_coin_balance_block_number %></span> <%= gettext("Last Balance Update: Block #") %><span data-selector="fetched-coin-balance-block-number"><%= @address.fetched_coin_balance_block_number %></span>
</span> </span>
<% end %>
<%= if validator?(@validation_count) do %> <%= if validator?(@validation_count) do %>
<span class="address-detail-item"> <span class="address-detail-item">
<span data-selector="validation-count"> <span data-selector="validation-count">

@ -40,7 +40,9 @@
</div> </div>
</div> </div>
<div data-selector="coin-balances-list" data-items></div> <div data-selector="coin-balances-list" data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -46,14 +46,18 @@
<dd class="col-sm-8 col-md-10"><%= @address.smart_contract.evm_version %></dd> <dd class="col-sm-8 col-md-10"><%= @address.smart_contract.evm_version %></dd>
</dl> </dl>
<% end %> <% end %>
<hr/>
<%= if @address.smart_contract.constructor_arguments do %> <%= if @address.smart_contract.constructor_arguments do %>
<dl class="row"> <section>
<dt class="col-sm-4 col-md-2 text-muted"><%= gettext "Constructor arguments" %></dt> <div class="d-flex justify-content-between align-items-baseline">
<dd class="col-sm-8 col-md-10"><%= @address.smart_contract.constructor_arguments %></dd> <h3><%= gettext "Constructor Arguments" %></h3>
</dl>
<% end %>
</div> </div>
<hr/> <div class="tile tile-muted mb-4">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= raw(format_constructor_arguments(@address.smart_contract)) %></code>
</pre>
</div>
</section>
<% end %>
<section> <section>
<div class="d-flex justify-content-between align-items-baseline"> <div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract source code" %></h3> <h3><%= gettext "Contract source code" %></h3>
@ -116,7 +120,7 @@
<h3><%= gettext "External libraries" %></h3> <h3><%= gettext "External libraries" %></h3>
</div> </div>
<div class="tile tile-muted mb-4"> <div class="tile tile-muted mb-4">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= format_external_libraries(@address.smart_contract.external_libraries) %></code> <pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= raw(format_external_libraries(@address.smart_contract.external_libraries)) %></code>
</pre> </pre>
</div> </div>
</section> </section>

@ -66,7 +66,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -11,6 +11,76 @@
) %> ) %>
</h3> </h3>
</dd> </dd>
<dt class="col-md-2"><%= gettext "Decoded" %></dt>
<dd class="col-md-10">
<%= case decode(@log, @log.transaction) do %>
<% {:error, :contract_not_verified} -> %>
<div class="alert alert-info">
<%= gettext "To see decoded input data, the contract must be verified." %>
<%= case @log.transaction do %>
<% %{to_address: %{hash: hash}} -> %>
<%= gettext "Verify the contract " %><a href="<%= address_verify_contract_path(@conn, :new, hash)%>"><%= gettext "here" %></a>
<% _ -> %>
<%= nil %>
<% end %>
</div>
<% {:error, :could_not_decode} -> %>
<div class="alert alert-danger">
<%= gettext "Failed to decode log data." %>
</div>
<% {:ok, method_id, text, mapping} -> %>
<table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table">
<tr>
<td>Method Id</td>
<td colspan="3"><code>0x<%= method_id %></code></td>
</tr>
<tr>
<td>Call</td>
<td colspan="3"><code><%= text %></code></td>
</tr>
</table>
<div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered">
<tr>
<th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th>
<th scope="col"><%= gettext "Type" %></th>
<th scope="col"><%= gettext "Indexed?" %></th>
<th scope="col"><%= gettext "Data" %></th>
<tr>
<%= for {name, type, indexed?, value} <- mapping do %>
<tr>
<th scope="row">
<%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
<% :error -> %>
<%= nil %>
<% copy_text -> %>
<span
aria-label='<%= gettext "Copy Value" %>'
class="btn-copy-ico"
data-clipboard-text="<%= copy_text %>"
data-placement="top"
data-toggle="tooltip"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32.5 32.5" width="32" height="32">
<path fill-rule="evenodd" d="M23.5 20.5a1 1 0 0 1-1-1v-9h-9a1 1 0 0 1 0-2h10a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zm-3-7v10a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1v-10a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1zm-2 1h-8v8h8v-8z"/>
</svg>
</span>
<% end %>
</th>
<td><%= name %></td>
<td><%= type %></td>
<td><%= indexed? %></td>
<td>
<pre class="transaction-input-text tile"><code><%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %></code></pre>
</td>
</tr>
<% end %>
</table>
</div>
<% _ -> %>
<%= nil %>
<% end %>
<dt class="col-md-2"><%= gettext "Topics" %></dt> <dt class="col-md-2"><%= gettext "Topics" %></dt>
<dd class="col-md-10"> <dd class="col-md-10">
<div class="raw-transaction-log-topics"> <div class="raw-transaction-log-topics">

@ -27,7 +27,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -19,7 +19,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<div class="transaction-bottom-panel"> <div class="transaction-bottom-panel">
<div csv-download class="download-all-transactions"> <div csv-download class="download-all-transactions">

@ -21,7 +21,9 @@
</span> </span>
</button> </button>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -65,7 +65,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<div class="transaction-bottom-panel"> <div class="transaction-bottom-panel">
<div class="download-all-transactions"> <div class="download-all-transactions">

@ -22,7 +22,9 @@
<%= gettext "Something went wrong, click to reload." %> <%= gettext "Something went wrong, click to reload." %>
</span> </span>
</button> </button>
<div data-items data-selector="validations-list"></div> <div data-items data-selector="validations-list">
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -11,7 +11,9 @@
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<div data-empty-response-message style="display: none;"> <div data-empty-response-message style="display: none;">
<span><%= gettext "There are no blocks." %></span> <span><%= gettext "There are no blocks." %></span>
</div> </div>

@ -29,7 +29,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -1,172 +1,5 @@
<div class="col-lg-3 fade-up-blocks-chain" data-selector="chain-block" data-block-number="<%= @block.number %>"> <div class="col-lg-3 fade-up-blocks-chain" data-selector="chain-block" data-block-number="<%= @block.number %>">
<div class="tile tile-type-block n-p d-flex flex-column"> <div class="tile tile-type-block n-p d-flex flex-column">
<div class="tile-type-block-animation">
<div class="tile-type-line-up"></div>
<span class="cube-animation-title">Block Validated, processing...</span>
<div class="cube-animation-wrapper">
<div class="cube-animation-center">
<div class="cube-animation-row">
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
</div>
<div class="cube-animation-row">
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
</div>
<div class="cube-animation-row">
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
</div>
</div>
</div>
</div>
<%= link( <%= link(
@block, @block,
class: "tile-title", class: "tile-title",

@ -5,7 +5,7 @@
<div class="dashboard-banner-network-graph"> <div class="dashboard-banner-network-graph">
<!-- Graph --> <!-- Graph -->
<div class="dashboard-banner-chart"> <div class="dashboard-banner-chart">
<div data-chart-loading-message class="tile tile-muted text-center mt-5"> <div hidden data-chart-loading-message class="tile tile-muted text-center mt-5">
<span class="loading-spinner-small mr-2"> <span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span> <span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span> <span class="loading-spinner-block-2"></span>
@ -91,7 +91,7 @@
<%= gettext "Something went wrong, click to reload." %> <%= gettext "Something went wrong, click to reload." %>
</span> </span>
</button> </button>
<div data-selector="loading-message" class="tile tile-muted text-center mt-3 w-100"> <div hidden data-selector="loading-message" class="tile tile-muted text-center mt-3 w-100" >
<span class="loading-spinner-small mr-2"> <span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span> <span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span> <span class="loading-spinner-block-2"></span>
@ -117,12 +117,8 @@
<%= gettext "Something went wrong, click to retry." %> <%= gettext "Something went wrong, click to retry." %>
</span> </span>
</button> </button>
<div data-selector="loading-message" class="tile tile-muted text-center mt-3"> <div hidden data-selector="loading-message">
<span class="loading-spinner-small mr-2"> <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
<span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span>
</span>
<%= gettext("Loading...") %>
</div> </div>
</span> </span>
</div> </div>

@ -0,0 +1,85 @@
<tr class="table-content-pseudo">
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
</tr>
<tr class="table-content-pseudo">
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
</tr>
<tr class="table-content-pseudo">
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
</tr>
<tr class="table-content-pseudo">
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
</tr>
<tr class="table-content-pseudo">
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
<td class="stakes-td">
<span class="table-content-loader"></span>
</td>
</tr>

@ -0,0 +1,72 @@
<div data-selector="loading-message" class="tile tile-type-loading">
<div class="row tile-body">
<div class="tile-transaction-type-block col-md-2 d-flex flex-row flex-md-column">
<span class="tile-label">
<span class="tile-loader tile-label-loader"></span>
</span>
<span class="tile-status-label ml-2 ml-md-0">
<span class="tile-loader tile-label-loader"></span>
</span>
</div>
<div class="col-md-7 col-lg-8 d-flex flex-column pr-2 pr-sm-2 pr-md-0">
<span class="tile-loader tile-address-loader"></span>
<span class="tile-loader tile-address-loader"></span>
</div>
<div class="col-md-3 col-lg-2 d-flex flex-row flex-md-column flex-nowrap justify-content-center text-md-right mt-3 mt-md-0 tile-bottom">
<span class="mr-2 mr-md-0 order-1">
<span class="tile-loader tile-label-loader"></span>
</span>
<span class="mr-2 mr-md-0 order-2">
<span class="tile-loader tile-label-loader"></span>
</span>
</div>
</div>
</div>
<div data-selector="loading-message" class="tile tile-type-loading">
<div class="row tile-body">
<div class="tile-transaction-type-block col-md-2 d-flex flex-row flex-md-column">
<span class="tile-label">
<span class="tile-loader tile-label-loader"></span>
</span>
<span class="tile-status-label ml-2 ml-md-0">
<span class="tile-loader tile-label-loader"></span>
</span>
</div>
<div class="col-md-7 col-lg-8 d-flex flex-column pr-2 pr-sm-2 pr-md-0">
<span class="tile-loader tile-address-loader"></span>
<span class="tile-loader tile-address-loader"></span>
</div>
<div class="col-md-3 col-lg-2 d-flex flex-row flex-md-column flex-nowrap justify-content-center text-md-right mt-3 mt-md-0 tile-bottom">
<span class="mr-2 mr-md-0 order-1">
<span class="tile-loader tile-label-loader"></span>
</span>
<span class="mr-2 mr-md-0 order-2">
<span class="tile-loader tile-label-loader"></span>
</span>
</div>
</div>
</div>
<div data-selector="loading-message" class="tile tile-type-loading">
<div class="row tile-body">
<div class="tile-transaction-type-block col-md-2 d-flex flex-row flex-md-column">
<span class="tile-label">
<span class="tile-loader tile-label-loader"></span>
</span>
<span class="tile-status-label ml-2 ml-md-0">
<span class="tile-loader tile-label-loader"></span>
</span>
</div>
<div class="col-md-7 col-lg-8 d-flex flex-column pr-2 pr-sm-2 pr-md-0">
<span class="tile-loader tile-address-loader"></span>
<span class="tile-loader tile-address-loader"></span>
</div>
<div class="col-md-3 col-lg-2 d-flex flex-row flex-md-column flex-nowrap justify-content-center text-md-right mt-3 mt-md-0 tile-bottom">
<span class="mr-2 mr-md-0 order-1">
<span class="tile-loader tile-label-loader"></span>
</span>
<span class="mr-2 mr-md-0 order-2">
<span class="tile-loader tile-label-loader"></span>
</span>
</div>
</div>
</div>

@ -1,8 +1,18 @@
<nav class="navbar navbar-dark navbar-expand-lg navbar-primary" data-selector="navbar"> <nav class="navbar navbar-dark navbar-expand-lg navbar-primary" data-selector="navbar" id="top-navbar">
<script>
if (localStorage.getItem("current-color-mode") === "dark") {
document.getElementById("top-navbar").style.backgroundColor = "#282945";
}
</script>
<div class="container-fluid navbar-container"> <div class="container-fluid navbar-container">
<%= link to: chain_path(@conn, :show), class: "navbar-brand", "data-test": "header_logo" do %> <%= link to: chain_path(@conn, :show), class: "navbar-brand", "data-test": "header_logo" do %>
<img class="navbar-logo" src="<%= logo() %>" alt="<%= subnetwork_title() %>" /> <img class="navbar-logo" id="navbar-logo" src="<%= logo() %>" alt="<%= subnetwork_title() %>" />
<% end %> <% end %>
<script>
if (localStorage.getItem("current-color-mode") === "dark") {
document.getElementById("navbar-logo").style.filter = "brightness(0) invert(1)";
}
</script>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="<%= gettext("Toggle navigation") %>"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="<%= gettext("Toggle navigation") %>">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
@ -90,8 +100,14 @@
</a> </a>
</li> </li>
</ul> </ul>
<!-- Dark mode changer -->
<button class="dark-mode-changer" id="dark-mode-changer">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="16">
<path fill="#9B62FF" fill-rule="evenodd" d="M14.88 11.578a.544.544 0 0 0-.599-.166 5.7 5.7 0 0 1-1.924.321c-3.259 0-5.91-2.632-5.91-5.866 0-1.947.968-3.759 2.59-4.849a.534.534 0 0 0-.225-.97A5.289 5.289 0 0 0 8.059 0C3.615 0 0 3.588 0 8s3.615 8 8.059 8c2.82 0 5.386-1.423 6.862-3.806a.533.533 0 0 0-.041-.616z"/>
</svg>
</button>
<!-- Search navbar --> <!-- Search navbar -->
<div class="search-form d-lg-flex d-inline-block"> <div class="search-form d-lg-flex d-inline-block" style="background-color: #22223a">
<%= form_for @conn, chain_path(@conn, :search), [class: "form-inline my-2 my-lg-0", method: :get, enforce_utf8: false], fn f -> %> <%= form_for @conn, chain_path(@conn, :search), [class: "form-inline my-2 my-lg-0", method: :get, enforce_utf8: false], fn f -> %>
<div class="input-group" title='<%= gettext("Search by address, token symbol name, transaction hash, or block number") %>'> <div class="input-group" title='<%= gettext("Search by address, token symbol name, transaction hash, or block number") %>'>
<%= awesomplete(f, :q, <%= awesomplete(f, :q,
@ -117,9 +133,22 @@
</div> </div>
</div> </div>
<button class="btn btn-outline-success my-2 my-sm-0 sr-only hidden" type="submit"><%= gettext "Search" %></button> <button class="btn btn-outline-success my-2 my-sm-0 sr-only hidden" type="submit"><%= gettext "Search" %></button>
<script>
if (localStorage.getItem("current-color-mode") === "dark") {
document.getElementById("q").style.backgroundColor = "#22223a";
document.getElementById("q").style.borderColor = "#22223a";
}
</script>
<% end %> <% end %>
</div> </div>
</div> </div>
</div> </div>
</nav> </nav>
<%= render BlockScoutWeb.LayoutView, "_network_selector.html" %> <%= render BlockScoutWeb.LayoutView, "_network_selector.html" %>
<script>
if (localStorage.getItem("current-color-mode") === "dark") {
var modeChanger = document.getElementById("dark-mode-changer");
modeChanger.className += " " + "dark-mode-changer--dark";
document.body.className += " " + "dark-theme-applied";
}
</script>

@ -24,6 +24,11 @@
</head> </head>
<body> <body>
<script>
if (localStorage.getItem("current-color-mode") === "dark") {
document.body.style.backgroundColor = "#1c1d31";
}
</script>
<div class="layout-container"> <div class="layout-container">
<%= if not Explorer.Chain.finished_indexing?() do %> <%= if not Explorer.Chain.finished_indexing?() do %>
<div class="alert alert-warning text-center mb-0 p-3" data-selector="indexed-status"> <div class="alert alert-warning text-center mb-0 p-3" data-selector="indexed-status">

@ -23,13 +23,8 @@
<%= gettext "There are no pending transactions." %> <%= gettext "There are no pending transactions." %>
</span> </span>
</div> </div>
<div data-items data-selector="transactions-pending-list"></div> <div data-items data-selector="transactions-pending-list">
<div data-loading-message class="tile tile-muted text-center mt-3" style="display: none;"> <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span>
</span>
<%= gettext("Loading") %>...
</div> </div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -28,7 +28,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -27,7 +27,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -26,7 +26,9 @@
</span> </span>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -1,4 +1,5 @@
<table summary="<%= gettext "Transaction Info" %>" class="table thead-light table-bordered table-responsive transaction-info-table"> <div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Transaction Inputs" %>" class="table thead-light table-bordered">
<tr> <tr>
<td><%= gettext "Method Id" %></td> <td><%= gettext "Method Id" %></td>
<td colspan="3"><code>0x<%= @method_id %></code></td> <td colspan="3"><code>0x<%= @method_id %></code></td>
@ -8,9 +9,11 @@
<td colspan="3"><code><%= @text %></code></td> <td colspan="3"><code><%= @text %></code></td>
</tr> </tr>
</table> </table>
</div>
<%= unless Enum.empty?(@mapping) do %> <%= unless Enum.empty?(@mapping) do %>
<table summary="<%= gettext "Transaction Inputs" %>" class="table thead-light table-bordered table-responsive"> <div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Transaction Inputs" %>" class="table thead-light table-bordered">
<tr> <tr>
<th scope="col"></th> <th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th> <th scope="col"><%= gettext "Name" %></th>
@ -52,4 +55,5 @@
</tr> </tr>
<% end %> <% end %>
</table> </table>
</div>
<% end %> <% end %>

@ -28,7 +28,9 @@
</div> </div>
</div> </div>
<div data-selector="transactions-list" data-items></div> <div data-selector="transactions-list" data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -16,7 +16,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
</div> </div>

@ -39,7 +39,8 @@
<td colspan="3"><code><%= text %></code></td> <td colspan="3"><code><%= text %></code></td>
</tr> </tr>
</table> </table>
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered table-responsive"> <div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered">
<tr> <tr>
<th scope="col"></th> <th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th> <th scope="col"><%= gettext "Name" %></th>
@ -76,6 +77,7 @@
</tr> </tr>
<% end %> <% end %>
</table> </table>
</div>
<% _ -> %> <% _ -> %>
<%= nil %> <%= nil %>
<% end %> <% end %>

@ -19,7 +19,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -18,7 +18,9 @@
</div> </div>
</div> </div>
<div data-items></div> <div data-items>
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>

@ -1,6 +1,7 @@
defmodule BlockScoutWeb.AddressContractView do defmodule BlockScoutWeb.AddressContractView do
use BlockScoutWeb, :view use BlockScoutWeb, :view
alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain.{Address, Data, InternalTransaction} alias Explorer.Chain.{Address, Data, InternalTransaction}
def render("scripts.html", %{conn: conn}) do def render("scripts.html", %{conn: conn}) do
@ -21,9 +22,44 @@ defmodule BlockScoutWeb.AddressContractView do
def format_optimization_text(true), do: gettext("true") def format_optimization_text(true), do: gettext("true")
def format_optimization_text(false), do: gettext("false") def format_optimization_text(false), do: gettext("false")
def format_constructor_arguments(contract) do
constructor_abi = Enum.find(contract.abi, fn el -> el["type"] == "constructor" && el["inputs"] != [] end)
input_types = Enum.map(constructor_abi["inputs"], &FunctionSelector.parse_specification_type/1)
{_, result} =
contract.constructor_arguments
|> decode_data(input_types)
|> Enum.zip(constructor_abi["inputs"])
|> Enum.reduce({0, "#{contract.constructor_arguments}\n\n"}, fn {val, %{"type" => type}}, {count, acc} ->
formatted_val =
if is_binary(val) do
Base.encode16(val, case: :lower)
else
val
end
{count + 1, "#{acc}Arg [#{count}] (<b>#{type}</b>) : #{formatted_val}\n"}
end)
result
rescue
_ -> contract.constructor_arguments
end
defp decode_data("0x" <> encoded_data, types) do
decode_data(encoded_data, types)
end
defp decode_data(encoded_data, types) do
encoded_data
|> Base.decode16!(case: :mixed)
|> TypeDecoder.decode_raw(types)
end
def format_external_libraries(libraries) do def format_external_libraries(libraries) do
Enum.reduce(libraries, "", fn %{name: name, address_hash: address_hash}, acc -> Enum.reduce(libraries, "", fn %{name: name, address_hash: address_hash}, acc ->
acc <> name <> " : " <> address_hash <> "\n" "#{acc}<span class=\"hljs-title\">#{name}</span> : #{address_hash} \n"
end) end)
end end

@ -1,3 +1,9 @@
defmodule BlockScoutWeb.AddressLogsView do defmodule BlockScoutWeb.AddressLogsView do
use BlockScoutWeb, :view use BlockScoutWeb, :view
alias Explorer.Chain.Log
def decode(log, transaction) do
Log.decode(log, transaction)
end
end end

@ -23,6 +23,7 @@ defmodule BlockScoutWeb.InternalTransactionView do
def type(%InternalTransaction{type: :call, call_type: :delegatecall}), do: gettext("Delegate Call") def type(%InternalTransaction{type: :call, call_type: :delegatecall}), do: gettext("Delegate Call")
def type(%InternalTransaction{type: :call, call_type: :staticcall}), do: gettext("Static Call") def type(%InternalTransaction{type: :call, call_type: :staticcall}), do: gettext("Static Call")
def type(%InternalTransaction{type: :create}), do: gettext("Create") def type(%InternalTransaction{type: :create}), do: gettext("Create")
def type(%InternalTransaction{type: :create2}), do: gettext("Create2")
def type(%InternalTransaction{type: :selfdestruct}), do: gettext("Self-Destruct") def type(%InternalTransaction{type: :selfdestruct}), do: gettext("Self-Destruct")
def type(%InternalTransaction{type: :reward}), do: gettext("Reward") def type(%InternalTransaction{type: :reward}), do: gettext("Reward")
end end

@ -125,7 +125,7 @@ defmodule BlockScoutWeb.Mixfile do
{:spandex_datadog, "~> 0.4.0"}, {:spandex_datadog, "~> 0.4.0"},
# `:spandex` tracing of `:phoenix` # `:spandex` tracing of `:phoenix`
{:spandex_phoenix, "~> 0.3.1"}, {:spandex_phoenix, "~> 0.3.1"},
{:timex, "~> 3.4"}, {:timex, "~> 3.6"},
{:wallaby, "~> 0.22", only: [:test], runtime: false}, {:wallaby, "~> 0.22", only: [:test], runtime: false},
# `:cowboy` `~> 2.0` and Phoenix 1.4 compatibility # `:cowboy` `~> 2.0` and Phoenix 1.4 compatibility
{:wobserver, "~> 0.2.0", github: "poanetwork/wobserver", branch: "support-https"}, {:wobserver, "~> 0.2.0", github: "poanetwork/wobserver", branch: "support-https"},

@ -34,7 +34,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:21 #: lib/block_scout_web/templates/block/overview.html.eex:21
#: lib/block_scout_web/templates/chain/_block.html.eex:178 #: lib/block_scout_web/templates/chain/_block.html.eex:11
msgid "%{count} Transactions" msgid "%{count} Transactions"
msgstr "" msgstr ""
@ -62,7 +62,7 @@ msgid "(query)"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:35 #: lib/block_scout_web/templates/layout/app.html.eex:40
msgid "- We're indexing this chain right now. Some of the counts may be inaccurate." msgid "- We're indexing this chain right now. Some of the counts may be inaccurate."
msgstr "" msgstr ""
@ -87,7 +87,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:56 #: lib/block_scout_web/templates/layout/_topnav.html.eex:66
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""
@ -157,7 +157,7 @@ msgid "Block Height: %{height}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:50 #: lib/block_scout_web/templates/layout/app.html.eex:55
msgid "Block Mined, awaiting import..." msgid "Block Mined, awaiting import..."
msgstr "" msgstr ""
@ -178,19 +178,19 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:87 #: lib/block_scout_web/templates/chain/show.html.eex:87
#: lib/block_scout_web/templates/layout/_topnav.html.eex:16 #: lib/block_scout_web/templates/layout/_topnav.html.eex:26
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20 #: lib/block_scout_web/templates/layout/_topnav.html.eex:30
msgid "Blocks" msgid "Blocks"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:49 #: lib/block_scout_web/templates/layout/app.html.eex:54
msgid "Blocks Indexed" msgid "Blocks Indexed"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:32 #: 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/overview.html.eex:97
#: lib/block_scout_web/templates/address_validation/index.html.eex:13 #: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:311 #: lib/block_scout_web/views/address_view.ex:311
msgid "Blocks Validated" msgid "Blocks Validated"
@ -209,8 +209,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:37 #: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:37
#: lib/block_scout_web/templates/address/overview.html.eex:144 #: lib/block_scout_web/templates/address/overview.html.eex:146
#: lib/block_scout_web/templates/address/overview.html.eex:152 #: lib/block_scout_web/templates/address/overview.html.eex:154
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:115 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:115
msgid "Close" msgid "Close"
@ -258,7 +258,7 @@ msgid "Connection Lost, click to load newer validations"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:71 #: lib/block_scout_web/templates/address_contract/index.html.eex:75
msgid "Contract ABI" msgid "Contract ABI"
msgstr "" msgstr ""
@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:59 #: lib/block_scout_web/templates/address_contract/index.html.eex:63
msgid "Contract source code" msgid "Contract source code"
msgstr "" msgstr ""
@ -319,7 +319,7 @@ msgid "Copy Txn Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:105 #: lib/block_scout_web/templates/address/overview.html.eex:107
msgid "Created by" msgid "Created by"
msgstr "" msgstr ""
@ -328,14 +328,6 @@ msgstr ""
msgid "Curl" msgid "Curl"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@ -376,7 +368,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_balance_card.html.eex:15 #: lib/block_scout_web/templates/address/_balance_card.html.eex:15
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21 #: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21
#: lib/block_scout_web/templates/layout/app.html.eex:55 #: lib/block_scout_web/templates/layout/app.html.eex:60
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20 #: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:30 #: lib/block_scout_web/templates/transaction/_tile.html.eex:30
#: lib/block_scout_web/templates/transaction/overview.html.eex:196 #: lib/block_scout_web/templates/transaction/overview.html.eex:196
@ -400,7 +392,7 @@ msgid "Fetching tokens..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:26 #: lib/block_scout_web/templates/layout/_topnav.html.eex:36
msgid "Forked Blocks (Reorgs)" msgid "Forked Blocks (Reorgs)"
msgstr "" msgstr ""
@ -454,7 +446,7 @@ msgid "IN"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:51 #: lib/block_scout_web/templates/layout/app.html.eex:56
msgid "Indexing Tokens" msgid "Indexing Tokens"
msgstr "" msgstr ""
@ -486,7 +478,7 @@ msgid "Inventory"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:52 #: lib/block_scout_web/templates/layout/app.html.eex:57
msgid "Less than" msgid "Less than"
msgstr "" msgstr ""
@ -507,7 +499,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:31 #: lib/block_scout_web/templates/chain/show.html.eex:31
#: lib/block_scout_web/templates/layout/app.html.eex:53 #: lib/block_scout_web/templates/layout/app.html.eex:58
#: lib/block_scout_web/views/address_view.ex:121 #: lib/block_scout_web/views/address_view.ex:121
#: lib/block_scout_web/views/address_view.ex:121 #: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap" msgid "Market Cap"
@ -522,7 +514,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38 #: 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/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:182 #: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner" msgid "Miner"
msgstr "" msgstr ""
@ -555,9 +547,10 @@ msgid "Must be set to:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: 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/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -604,7 +597,7 @@ msgid "Parent Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:44 #: lib/block_scout_web/templates/layout/_topnav.html.eex:54
#: lib/block_scout_web/views/transaction_view.ex:143 #: lib/block_scout_web/views/transaction_view.ex:143
#: lib/block_scout_web/views/transaction_view.ex:177 #: lib/block_scout_web/views/transaction_view.ex:177
msgid "Pending" msgid "Pending"
@ -622,13 +615,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:24 #: lib/block_scout_web/templates/chain/show.html.eex:24
#: lib/block_scout_web/templates/layout/app.html.eex:54 #: lib/block_scout_web/templates/layout/app.html.eex:59
msgid "Price" msgid "Price"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:33 #: lib/block_scout_web/templates/address/overview.html.eex:33
#: lib/block_scout_web/templates/address/overview.html.eex:143 #: lib/block_scout_web/templates/address/overview.html.eex:145
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:36 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:36
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106
msgid "QR Code" msgid "QR Code"
@ -669,8 +662,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:102 #: lib/block_scout_web/templates/layout/_topnav.html.eex:118
#: lib/block_scout_web/templates/layout/_topnav.html.eex:119 #: lib/block_scout_web/templates/layout/_topnav.html.eex:135
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -774,7 +767,7 @@ msgid "To"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:6 #: lib/block_scout_web/templates/layout/_topnav.html.eex:16
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "" msgstr ""
@ -825,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer" msgid "Top Accounts - %{subnetwork} Explorer"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67 #: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty" msgid "Total Difficulty"
@ -873,7 +860,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10 #: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:18 #: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: lib/block_scout_web/templates/chain/show.html.eex:108 #: lib/block_scout_web/templates/chain/show.html.eex:108
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35 #: lib/block_scout_web/templates/layout/_topnav.html.eex:45
#: lib/block_scout_web/views/address_view.ex:305 #: lib/block_scout_web/views/address_view.ex:305
msgid "Transactions" msgid "Transactions"
msgstr "" msgstr ""
@ -900,7 +887,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:80 #: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23 #: lib/block_scout_web/templates/layout/_topnav.html.eex:33
msgid "Uncles" msgid "Uncles"
msgstr "" msgstr ""
@ -915,7 +902,7 @@ msgid "Used"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:39 #: lib/block_scout_web/templates/layout/_topnav.html.eex:49
msgid "Validated" msgid "Validated"
msgstr "" msgstr ""
@ -996,12 +983,12 @@ msgid "Yes"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:111 #: lib/block_scout_web/templates/address/overview.html.eex:113
msgid "at" msgid "at"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:22 #: lib/block_scout_web/views/address_contract_view.ex:23
msgid "false" msgid "false"
msgstr "" msgstr ""
@ -1019,7 +1006,7 @@ msgid "string"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:21 #: lib/block_scout_web/views/address_contract_view.ex:22
msgid "true" msgid "true"
msgstr "" msgstr ""
@ -1039,14 +1026,7 @@ msgid "Delegate Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:190
#: lib/block_scout_web/views/internal_transaction_view.ex:27 #: lib/block_scout_web/views/internal_transaction_view.ex:27
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct" msgid "Self-Destruct"
msgstr "" msgstr ""
@ -1058,7 +1038,6 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:14 #: lib/block_scout_web/templates/address_read_contract/index.html.eex:14
#: lib/block_scout_web/templates/chain/show.html.eex:99 #: 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 #: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:21
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
@ -1069,22 +1048,17 @@ msgid "Loading...."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:64 #: lib/block_scout_web/templates/layout/_topnav.html.eex:74
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:68 #: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:32 #: lib/block_scout_web/templates/layout/_topnav.html.eex:83
msgid "Loading"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:73
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1134,48 +1108,37 @@ msgid "Static Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14
msgid "Decoded" msgid "Decoded"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
msgid "Method Id" msgid "Method Id"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19
msgid "To see decoded input data, the contract must be verified." msgid "To see decoded input data, the contract must be verified."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
msgid "Transaction Info" #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
msgid "Transaction Inputs" msgid "Transaction Inputs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:22
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "Verify the contract " msgid "Verify the contract "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:22
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "here" msgid "here"
@ -1187,26 +1150,10 @@ msgid "Failed to decode input data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value" msgid "Error rendering value"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Log Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34 #: 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_internal_transaction/index.html.eex:61
@ -1277,7 +1224,7 @@ msgid "There are no pending transactions."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/index.html.eex:16 #: lib/block_scout_web/templates/block/index.html.eex:18
msgid "There are no blocks." msgid "There are no blocks."
msgstr "" msgstr ""
@ -1407,17 +1354,17 @@ msgid "Support"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:73 #: lib/block_scout_web/templates/address_contract/index.html.eex:77
msgid "Copy ABI" msgid "Copy ABI"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:89 #: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Copy Contract Creation Code" msgid "Copy Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:61 #: lib/block_scout_web/templates/address_contract/index.html.eex:65
msgid "Copy Source Code" msgid "Copy Source Code"
msgstr "" msgstr ""
@ -1432,7 +1379,7 @@ msgid "Contract Libraries"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:88 #: lib/block_scout_web/templates/address/overview.html.eex:89
msgid "Last Balance Update: Block #" msgid "Last Balance Update: Block #"
msgstr "" msgstr ""
@ -1478,13 +1425,13 @@ msgid "Incoming Transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:119 #: lib/block_scout_web/templates/address/overview.html.eex:121
msgid "Error: Could not determine contract creator." msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:96 #: lib/block_scout_web/templates/layout/_topnav.html.eex:112
#: lib/block_scout_web/templates/layout/_topnav.html.eex:100 #: lib/block_scout_web/templates/layout/_topnav.html.eex:116
msgid "Search by address, token symbol name, transaction hash, or block number" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1587,27 +1534,27 @@ msgid "Block Details"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:101 #: lib/block_scout_web/templates/address_contract/index.html.eex:105
msgid "Contract Byte Code" msgid "Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:87 #: lib/block_scout_web/templates/address_contract/index.html.eex:91
msgid "Contract Creation Code" msgid "Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:93 #: lib/block_scout_web/templates/address_contract/index.html.eex:97
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified." msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:103 #: lib/block_scout_web/templates/address_contract/index.html.eex:107
msgid "Copy Contract Byte Code" msgid "Copy Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:94 #: lib/block_scout_web/templates/address_contract/index.html.eex:98
msgid "Displaying the init data provided of the creating transaction." msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
@ -1710,7 +1657,7 @@ msgid "ETH RPC API Documentation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:78 #: lib/block_scout_web/templates/layout/_topnav.html.eex:88
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -1745,8 +1692,8 @@ msgid "here."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:26 #: lib/block_scout_web/templates/address_token/index.html.eex:28
#: lib/block_scout_web/templates/address_transaction/index.html.eex:72 #: lib/block_scout_web/templates/address_transaction/index.html.eex:74
msgid "CSV" msgid "CSV"
msgstr "" msgstr ""
@ -1755,11 +1702,6 @@ msgstr ""
msgid "Change Network" msgid "Change Network"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:51
msgid "Constructor arguments"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:44 #: lib/block_scout_web/views/transaction_view.ex:44
msgid "ERC-20 " msgid "ERC-20 "
@ -1771,7 +1713,7 @@ msgid "ERC-721 "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:116 #: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "External libraries" msgid "External libraries"
msgstr "" msgstr ""
@ -1804,3 +1746,67 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost" msgid "Connection Lost"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Constructor Arguments"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Create2"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115
msgid "Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
msgid "Log Data"
msgstr ""
#, elixir-format
#: 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:28
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Type"
msgstr ""

@ -62,7 +62,7 @@ msgid "(query)"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:35 #: lib/block_scout_web/templates/layout/app.html.eex:40
msgid "- We're indexing this chain right now. Some of the counts may be inaccurate." msgid "- We're indexing this chain right now. Some of the counts may be inaccurate."
msgstr "" msgstr ""
@ -87,7 +87,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:56 #: lib/block_scout_web/templates/layout/_topnav.html.eex:66
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""
@ -157,7 +157,7 @@ msgid "Block Height: %{height}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:50 #: lib/block_scout_web/templates/layout/app.html.eex:55
msgid "Block Mined, awaiting import..." msgid "Block Mined, awaiting import..."
msgstr "" msgstr ""
@ -178,19 +178,19 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:87 #: lib/block_scout_web/templates/chain/show.html.eex:87
#: lib/block_scout_web/templates/layout/_topnav.html.eex:16 #: lib/block_scout_web/templates/layout/_topnav.html.eex:26
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20 #: lib/block_scout_web/templates/layout/_topnav.html.eex:30
msgid "Blocks" msgid "Blocks"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:49 #: lib/block_scout_web/templates/layout/app.html.eex:54
msgid "Blocks Indexed" msgid "Blocks Indexed"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:32 #: 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/overview.html.eex:97
#: lib/block_scout_web/templates/address_validation/index.html.eex:13 #: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:311 #: lib/block_scout_web/views/address_view.ex:311
msgid "Blocks Validated" msgid "Blocks Validated"
@ -209,8 +209,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:37 #: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:37
#: lib/block_scout_web/templates/address/overview.html.eex:144 #: lib/block_scout_web/templates/address/overview.html.eex:146
#: lib/block_scout_web/templates/address/overview.html.eex:152 #: lib/block_scout_web/templates/address/overview.html.eex:154
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:115 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:115
msgid "Close" msgid "Close"
@ -258,7 +258,7 @@ msgid "Connection Lost, click to load newer validations"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:71 #: lib/block_scout_web/templates/address_contract/index.html.eex:75
msgid "Contract ABI" msgid "Contract ABI"
msgstr "" msgstr ""
@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:59 #: lib/block_scout_web/templates/address_contract/index.html.eex:63
msgid "Contract source code" msgid "Contract source code"
msgstr "" msgstr ""
@ -319,7 +319,7 @@ msgid "Copy Txn Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:105 #: lib/block_scout_web/templates/address/overview.html.eex:107
msgid "Created by" msgid "Created by"
msgstr "" msgstr ""
@ -328,14 +328,6 @@ msgstr ""
msgid "Curl" msgid "Curl"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@ -376,7 +368,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_balance_card.html.eex:15 #: lib/block_scout_web/templates/address/_balance_card.html.eex:15
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21 #: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21
#: lib/block_scout_web/templates/layout/app.html.eex:55 #: lib/block_scout_web/templates/layout/app.html.eex:60
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20 #: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:30 #: lib/block_scout_web/templates/transaction/_tile.html.eex:30
#: lib/block_scout_web/templates/transaction/overview.html.eex:196 #: lib/block_scout_web/templates/transaction/overview.html.eex:196
@ -400,7 +392,7 @@ msgid "Fetching tokens..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:26 #: lib/block_scout_web/templates/layout/_topnav.html.eex:36
msgid "Forked Blocks (Reorgs)" msgid "Forked Blocks (Reorgs)"
msgstr "" msgstr ""
@ -454,7 +446,7 @@ msgid "IN"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:51 #: lib/block_scout_web/templates/layout/app.html.eex:56
msgid "Indexing Tokens" msgid "Indexing Tokens"
msgstr "" msgstr ""
@ -486,7 +478,7 @@ msgid "Inventory"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:52 #: lib/block_scout_web/templates/layout/app.html.eex:57
msgid "Less than" msgid "Less than"
msgstr "" msgstr ""
@ -507,7 +499,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:31 #: lib/block_scout_web/templates/chain/show.html.eex:31
#: lib/block_scout_web/templates/layout/app.html.eex:53 #: lib/block_scout_web/templates/layout/app.html.eex:58
#: lib/block_scout_web/views/address_view.ex:121 #: lib/block_scout_web/views/address_view.ex:121
#: lib/block_scout_web/views/address_view.ex:121 #: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap" msgid "Market Cap"
@ -555,9 +547,10 @@ msgid "Must be set to:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: 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/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -604,7 +597,7 @@ msgid "Parent Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:44 #: lib/block_scout_web/templates/layout/_topnav.html.eex:54
#: lib/block_scout_web/views/transaction_view.ex:143 #: lib/block_scout_web/views/transaction_view.ex:143
#: lib/block_scout_web/views/transaction_view.ex:177 #: lib/block_scout_web/views/transaction_view.ex:177
msgid "Pending" msgid "Pending"
@ -622,13 +615,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:24 #: lib/block_scout_web/templates/chain/show.html.eex:24
#: lib/block_scout_web/templates/layout/app.html.eex:54 #: lib/block_scout_web/templates/layout/app.html.eex:59
msgid "Price" msgid "Price"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:33 #: lib/block_scout_web/templates/address/overview.html.eex:33
#: lib/block_scout_web/templates/address/overview.html.eex:143 #: lib/block_scout_web/templates/address/overview.html.eex:145
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:36 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:36
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106
msgid "QR Code" msgid "QR Code"
@ -669,8 +662,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:102 #: lib/block_scout_web/templates/layout/_topnav.html.eex:118
#: lib/block_scout_web/templates/layout/_topnav.html.eex:119 #: lib/block_scout_web/templates/layout/_topnav.html.eex:135
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -774,7 +767,7 @@ msgid "To"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:6 #: lib/block_scout_web/templates/layout/_topnav.html.eex:16
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "" msgstr ""
@ -825,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer" msgid "Top Accounts - %{subnetwork} Explorer"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67 #: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty" msgid "Total Difficulty"
@ -873,7 +860,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10 #: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:18 #: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: lib/block_scout_web/templates/chain/show.html.eex:108 #: lib/block_scout_web/templates/chain/show.html.eex:108
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35 #: lib/block_scout_web/templates/layout/_topnav.html.eex:45
#: lib/block_scout_web/views/address_view.ex:305 #: lib/block_scout_web/views/address_view.ex:305
msgid "Transactions" msgid "Transactions"
msgstr "" msgstr ""
@ -900,7 +887,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:80 #: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23 #: lib/block_scout_web/templates/layout/_topnav.html.eex:33
msgid "Uncles" msgid "Uncles"
msgstr "" msgstr ""
@ -915,7 +902,7 @@ msgid "Used"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:39 #: lib/block_scout_web/templates/layout/_topnav.html.eex:49
msgid "Validated" msgid "Validated"
msgstr "" msgstr ""
@ -996,12 +983,12 @@ msgid "Yes"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:111 #: lib/block_scout_web/templates/address/overview.html.eex:113
msgid "at" msgid "at"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:22 #: lib/block_scout_web/views/address_contract_view.ex:23
msgid "false" msgid "false"
msgstr "" msgstr ""
@ -1019,7 +1006,7 @@ msgid "string"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:21 #: lib/block_scout_web/views/address_contract_view.ex:22
msgid "true" msgid "true"
msgstr "" msgstr ""
@ -1039,14 +1026,7 @@ msgid "Delegate Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: 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 #: lib/block_scout_web/views/internal_transaction_view.ex:27
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct" msgid "Self-Destruct"
msgstr "" msgstr ""
@ -1058,7 +1038,6 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:14 #: lib/block_scout_web/templates/address_read_contract/index.html.eex:14
#: lib/block_scout_web/templates/chain/show.html.eex:99 #: 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 #: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:21
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
@ -1069,22 +1048,17 @@ msgid "Loading...."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:64 #: lib/block_scout_web/templates/layout/_topnav.html.eex:74
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:68 #: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:32 #: lib/block_scout_web/templates/layout/_topnav.html.eex:83
msgid "Loading"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:73
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1134,48 +1108,37 @@ msgid "Static Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14
msgid "Decoded" msgid "Decoded"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
msgid "Method Id" msgid "Method Id"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19
msgid "To see decoded input data, the contract must be verified." msgid "To see decoded input data, the contract must be verified."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
msgid "Transaction Info" #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
msgid "Transaction Inputs" msgid "Transaction Inputs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:22
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "Verify the contract " msgid "Verify the contract "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:22
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "here" msgid "here"
@ -1187,25 +1150,10 @@ msgid "Failed to decode input data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value" msgid "Error rendering value"
msgstr "" msgstr ""
""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Log Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34 #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
@ -1277,7 +1225,7 @@ msgid "There are no pending transactions."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/index.html.eex:16 #: lib/block_scout_web/templates/block/index.html.eex:18
msgid "There are no blocks." msgid "There are no blocks."
msgstr "" msgstr ""
@ -1407,17 +1355,17 @@ msgid "Support"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:73 #: lib/block_scout_web/templates/address_contract/index.html.eex:77
msgid "Copy ABI" msgid "Copy ABI"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:89 #: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Copy Contract Creation Code" msgid "Copy Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:61 #: lib/block_scout_web/templates/address_contract/index.html.eex:65
msgid "Copy Source Code" msgid "Copy Source Code"
msgstr "" msgstr ""
@ -1432,7 +1380,7 @@ msgid "Contract Libraries"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:88 #: lib/block_scout_web/templates/address/overview.html.eex:89
msgid "Last Balance Update: Block #" msgid "Last Balance Update: Block #"
msgstr "" msgstr ""
@ -1478,13 +1426,13 @@ msgid "Incoming Transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:119 #: lib/block_scout_web/templates/address/overview.html.eex:121
msgid "Error: Could not determine contract creator." msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:96 #: lib/block_scout_web/templates/layout/_topnav.html.eex:112
#: lib/block_scout_web/templates/layout/_topnav.html.eex:100 #: lib/block_scout_web/templates/layout/_topnav.html.eex:116
msgid "Search by address, token symbol name, transaction hash, or block number" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1587,27 +1535,27 @@ msgid "Block Details"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:101 #: lib/block_scout_web/templates/address_contract/index.html.eex:105
msgid "Contract Byte Code" msgid "Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:87 #: lib/block_scout_web/templates/address_contract/index.html.eex:91
msgid "Contract Creation Code" msgid "Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:93 #: lib/block_scout_web/templates/address_contract/index.html.eex:97
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified." msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:103 #: lib/block_scout_web/templates/address_contract/index.html.eex:107
msgid "Copy Contract Byte Code" msgid "Copy Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:94 #: lib/block_scout_web/templates/address_contract/index.html.eex:98
msgid "Displaying the init data provided of the creating transaction." msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
@ -1710,7 +1658,7 @@ msgid "ETH RPC API Documentation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:78 #: lib/block_scout_web/templates/layout/_topnav.html.eex:88
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -1745,8 +1693,8 @@ msgid "here."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:26 #: lib/block_scout_web/templates/address_token/index.html.eex:28
#: lib/block_scout_web/templates/address_transaction/index.html.eex:72 #: lib/block_scout_web/templates/address_transaction/index.html.eex:74
msgid "CSV" msgid "CSV"
msgstr "" msgstr ""
@ -1755,11 +1703,6 @@ msgstr ""
msgid "Change Network" msgid "Change Network"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:51
msgid "Constructor arguments"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:44 #: lib/block_scout_web/views/transaction_view.ex:44
msgid "ERC-20 " msgid "ERC-20 "
@ -1771,7 +1714,7 @@ msgid "ERC-721 "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:116 #: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "External libraries" msgid "External libraries"
msgstr "" msgstr ""
@ -1804,3 +1747,67 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost" msgid "Connection Lost"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Constructor Arguments"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Create2"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115
msgid "Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
msgid "Log Data"
msgstr ""
#, elixir-format
#: 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:28
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Type"
msgstr ""

@ -13,10 +13,16 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
assert html_response(conn, 422) assert html_response(conn, 422)
end end
test "with valid address hash without address", %{conn: conn} do test "with valid address hash without address in the DB", %{conn: conn} do
conn = get(conn, address_transaction_path(conn, :index, "0x8bf38d4764929064f2d4d3a56520a76ab3df415b")) conn =
get(
conn,
address_transaction_path(conn, :index, "0x8bf38d4764929064f2d4d3a56520a76ab3df415b", %{"type" => "JSON"})
)
assert html_response(conn, 404) assert json_response(conn, 200)
transaction_tiles = json_response(conn, 200)["items"]
assert transaction_tiles |> length() == 0
end end
test "returns transactions for the address", %{conn: conn} do test "returns transactions for the address", %{conn: conn} do

@ -1,6 +1,15 @@
defmodule BlockScoutWeb.API.V1.HealthControllerTest do defmodule BlockScoutWeb.API.V1.HealthControllerTest do
use BlockScoutWeb.ConnCase use BlockScoutWeb.ConnCase
alias Explorer.{Chain, PagingOptions}
setup do
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
:ok
end
describe "GET last_block_status/0" do describe "GET last_block_status/0" do
test "returns error when there are no blocks in db", %{conn: conn} do test "returns error when there are no blocks in db", %{conn: conn} do
request = get(conn, api_v1_health_path(conn, :health)) request = get(conn, api_v1_health_path(conn, :health))
@ -32,14 +41,46 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do
end end
test "returns ok when last block is not stale", %{conn: conn} do test "returns ok when last block is not stale", %{conn: conn} do
insert(:block, consensus: true, timestamp: DateTime.utc_now()) block1 = insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 2)
insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
request = get(conn, api_v1_health_path(conn, :health)) request = get(conn, api_v1_health_path(conn, :health))
assert request.status == 200 assert request.status == 200
result = Poison.decode!(request.resp_body)
assert result["healthy"] == true
assert %{
"latest_block_number" => to_string(block1.number),
"latest_block_inserted_at" => to_string(block1.timestamp),
"cache_latest_block_number" => to_string(block1.number),
"cache_latest_block_inserted_at" => to_string(block1.timestamp)
} == result["data"]
end
end
test "return error when cache is stale", %{conn: conn} do
stale_block = insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50), number: 3)
state_block_hash = stale_block.hash
assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
request = get(conn, api_v1_health_path(conn, :health))
assert request.status == 500
assert %{ assert %{
"healthy" => true, "healthy" => false,
"error_code" => 5001,
"error_title" => "blocks fetching is stuck",
"error_description" =>
"There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance",
"data" => %{ "data" => %{
"latest_block_number" => _, "latest_block_number" => _,
"latest_block_inserted_at" => _ "latest_block_inserted_at" => _
@ -47,4 +88,3 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do
} = Poison.decode!(request.resp_body) } = Poison.decode!(request.resp_body)
end end
end end
end

@ -426,13 +426,14 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash, "transactionHash" => transaction_hash,
"index" => index, "index" => index,
"traceAddress" => trace_address, "traceAddress" => trace_address,
"type" => "create" = type, "type" => type,
"from" => from_address_hash, "from" => from_address_hash,
"error" => error, "error" => error,
"gas" => gas, "gas" => gas,
"init" => init, "init" => init,
"value" => value "value" => value
}) do })
when type in ~w(create create2) do
%{ %{
block_number: block_number, block_number: block_number,
transaction_index: transaction_index, transaction_index: transaction_index,
@ -454,7 +455,7 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash, "transactionHash" => transaction_hash,
"index" => index, "index" => index,
"traceAddress" => trace_address, "traceAddress" => trace_address,
"type" => "create", "type" => type,
"from" => from_address_hash, "from" => from_address_hash,
"createdContractAddressHash" => created_contract_address_hash, "createdContractAddressHash" => created_contract_address_hash,
"gas" => gas, "gas" => gas,
@ -462,14 +463,15 @@ defmodule EthereumJSONRPC.Geth.Call do
"init" => init, "init" => init,
"createdContractCode" => created_contract_code, "createdContractCode" => created_contract_code,
"value" => value "value" => value
}) do })
when type in ~w(create create2) do
%{ %{
block_number: block_number, block_number: block_number,
transaction_index: transaction_index, transaction_index: transaction_index,
transaction_hash: transaction_hash, transaction_hash: transaction_hash,
index: index, index: index,
trace_address: trace_address, trace_address: trace_address,
type: "create", type: type,
from_address_hash: from_address_hash, from_address_hash: from_address_hash,
gas: gas, gas: gas,
gas_used: gas_used, gas_used: gas_used,

@ -113,6 +113,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
end end
defp op(%{"op" => "CREATE"} = log, ctx), do: create_op(log, ctx) defp op(%{"op" => "CREATE"} = log, ctx), do: create_op(log, ctx)
defp op(%{"op" => "CREATE2"} = log, ctx), do: create_op(log, ctx, "create2")
defp op(%{"op" => "SELFDESTRUCT"} = log, ctx), do: self_destruct_op(log, ctx) defp op(%{"op" => "SELFDESTRUCT"} = log, ctx), do: self_destruct_op(log, ctx)
defp op(%{"op" => "CALL"} = log, ctx), do: call_op(log, "call", ctx) defp op(%{"op" => "CALL"} = log, ctx), do: call_op(log, "call", ctx)
defp op(%{"op" => "CALLCODE"} = log, ctx), do: call_op(log, "callcode", ctx) defp op(%{"op" => "CALLCODE"} = log, ctx), do: call_op(log, "callcode", ctx)
@ -155,7 +156,8 @@ defmodule EthereumJSONRPC.Geth.Tracer do
defp create_op( defp create_op(
%{"stack" => log_stack, "memory" => log_memory}, %{"stack" => log_stack, "memory" => log_memory},
%{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx %{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx,
type \\ "create"
) do ) do
[value, input_offset, input_length | _] = Enum.reverse(log_stack) [value, input_offset, input_length | _] = Enum.reverse(log_stack)
@ -165,7 +167,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
|> String.slice(quantity_to_integer("0x" <> input_offset) * 2, quantity_to_integer("0x" <> input_length) * 2) |> String.slice(quantity_to_integer("0x" <> input_offset) * 2, quantity_to_integer("0x" <> input_length) * 2)
call = %{ call = %{
"type" => "create", "type" => type,
"from" => nil, "from" => nil,
"traceAddress" => Enum.reverse(trace_address), "traceAddress" => Enum.reverse(trace_address),
"init" => "0x" <> init, "init" => "0x" <> init,

@ -353,4 +353,8 @@ defmodule EthereumJSONRPC.Transaction do
_ -> {key, quantity_to_integer(chain_id)} _ -> {key, quantity_to_integer(chain_id)}
end end
end end
defp entry_to_elixir(_) do
{nil, nil}
end
end end

@ -82,7 +82,7 @@ defmodule EthereumJsonrpc.MixProject do
# `:spandex` integration with Datadog # `:spandex` integration with Datadog
{:spandex_datadog, "~> 0.4.0"}, {:spandex_datadog, "~> 0.4.0"},
# Convert unix timestamps in JSONRPC to DateTimes # Convert unix timestamps in JSONRPC to DateTimes
{:timex, "~> 3.4"}, {:timex, "~> 3.6"},
# Encode/decode function names and arguments # Encode/decode function names and arguments
{:ex_abi, "~> 0.1.18"}, {:ex_abi, "~> 0.1.18"},
# `:verify_fun` for `Socket.Web.connect` # `:verify_fun` for `Socket.Web.connect`

@ -91,6 +91,9 @@
case 'CREATE': case 'CREATE':
this.createOp(log); this.createOp(log);
break; break;
case 'CREATE2':
this.create2Op(log);
break;
case 'SELFDESTRUCT': case 'SELFDESTRUCT':
this.selfDestructOp(log, db); this.selfDestructOp(log, db);
break; break;
@ -127,7 +130,7 @@
const ret = log.stack.peek(0); const ret = log.stack.peek(0);
if (!ret.equals(0)) { if (!ret.equals(0)) {
if (call.type === 'create') { if (call.type === 'create' || call.type === 'create2') {
call.createdContractAddressHash = toHex(toAddress(ret.toString(16))); call.createdContractAddressHash = toHex(toAddress(ret.toString(16)));
call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16)))); call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16))));
} else { } else {
@ -162,6 +165,21 @@
this.callStack.push(call); this.callStack.push(call);
}, },
create2Op(log) {
const inputOffset = log.stack.peek(1).valueOf();
const inputLength = log.stack.peek(2).valueOf();
const inputEnd = inputOffset + inputLength;
const stackValue = log.stack.peek(0);
const call = {
type: 'create2',
from: toHex(log.contract.getAddress()),
init: toHex(log.memory.slice(inputOffset, inputEnd)),
valueBigInt: bigInt(stackValue.toString(10))
};
this.callStack.push(call);
},
selfDestructOp(log, db) { selfDestructOp(log, db) {
const contractAddress = log.contract.getAddress(); const contractAddress = log.contract.getAddress();
@ -243,6 +261,9 @@
case 'CREATE': case 'CREATE':
result = this.ctxToCreate(ctx, db); result = this.ctxToCreate(ctx, db);
break; break;
case 'CREATE2':
result = this.ctxToCreate2(ctx, db);
break;
} }
return result; return result;
@ -292,6 +313,22 @@
return result; return result;
}, },
ctxToCreate2(ctx, db) {
const result = {
type: 'create2',
from: toHex(ctx.from),
init: toHex(ctx.input),
valueBigInt: bigInt(ctx.value.toString(10)),
gasBigInt: bigInt(ctx.gas),
gasUsedBigInt: bigInt(ctx.gasUsed)
};
this.putBottomChildCalls(result);
this.putErrorOrCreatedContract(result, ctx, db);
return result;
},
putBottomChildCalls(result) { putBottomChildCalls(result) {
const bottomCall = this.bottomCall(); const bottomCall = this.bottomCall();
const bottomChildCalls = bottomCall.calls; const bottomChildCalls = bottomCall.calls;
@ -422,4 +459,3 @@
call.gasUsed = '0x' + gasUsedBigInt.toString(16); call.gasUsed = '0x' + gasUsedBigInt.toString(16);
} }
} }

@ -2,4 +2,14 @@ defmodule EthereumJSONRPC.TransactionTest do
use ExUnit.Case, async: true use ExUnit.Case, async: true
doctest EthereumJSONRPC.Transaction doctest EthereumJSONRPC.Transaction
alias EthereumJSONRPC.Transaction
describe "to_elixir/1" do
test "skips unsupported keys" do
map = %{"key" => "value", "key1" => "value1"}
assert %{nil: nil} = Transaction.to_elixir(map)
end
end
end end

@ -17,7 +17,15 @@ config :explorer,
if(System.get_env("UNCLES_IN_AVERAGE_BLOCK_TIME") == "false", do: false, else: true), if(System.get_env("UNCLES_IN_AVERAGE_BLOCK_TIME") == "false", do: false, else: true),
healthy_blocks_period: System.get_env("HEALTHY_BLOCKS_PERIOD") || :timer.minutes(5) healthy_blocks_period: System.get_env("HEALTHY_BLOCKS_PERIOD") || :timer.minutes(5)
config :explorer, Explorer.Counters.AverageBlockTime, enabled: true average_block_period =
case Integer.parse(System.get_env("AVERAGE_BLOCK_CACHE_PERIOD", "")) do
{secs, ""} -> :timer.seconds(secs)
_ -> :timer.minutes(30)
end
config :explorer, Explorer.Counters.AverageBlockTime,
enabled: true,
period: average_block_period
config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true
@ -106,6 +114,14 @@ config :spandex_ecto, SpandexEcto.EctoLogger,
tracer: Explorer.Tracer, tracer: Explorer.Tracer,
otp_app: :explorer otp_app: :explorer
market_history_cache_period =
case Integer.parse(System.get_env("MARKET_HISTORY_CACHE_PERIOD", "")) do
{secs, ""} -> :timer.seconds(secs)
_ -> :timer.hours(6)
end
config :explorer, Explorer.Market.MarketHistoryCache, period: market_history_cache_period
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs" import_config "#{Mix.env()}.exs"

@ -273,7 +273,7 @@ defmodule Explorer.Chain do
from(log in Log, from(log in Log,
inner_join: transaction in assoc(log, :transaction), inner_join: transaction in assoc(log, :transaction),
order_by: [desc: transaction.block_number, desc: transaction.index], order_by: [desc: transaction.block_number, desc: transaction.index],
preload: [:transaction], preload: [:transaction, transaction: [to_address: :smart_contract]],
where: transaction.block_number < ^block_number, where: transaction.block_number < ^block_number,
or_where: transaction.block_number == ^block_number and transaction.index > ^transaction_index, or_where: transaction.block_number == ^block_number and transaction.index > ^transaction_index,
or_where: or_where:
@ -364,8 +364,8 @@ defmodule Explorer.Chain do
Uncles are not currently accounted for. Uncles are not currently accounted for.
""" """
@spec block_reward(Block.t()) :: Wei.t() @spec block_reward(Block.block_number()) :: Wei.t()
def block_reward(%Block{number: block_number}) do def block_reward(block_number) do
query = query =
from( from(
block in Block, block in Block,
@ -415,8 +415,8 @@ defmodule Explorer.Chain do
`:key` (a tuple of the lowest/oldest `{index}`) and. Results will be the transactions older than `:key` (a tuple of the lowest/oldest `{index}`) and. Results will be the transactions older than
the `index` that are passed. the `index` that are passed.
""" """
@spec block_to_transactions(Block.t(), [paging_options | necessity_by_association_option]) :: [Transaction.t()] @spec block_to_transactions(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [Transaction.t()]
def block_to_transactions(%Block{hash: block_hash}, options \\ []) when is_list(options) do def block_to_transactions(block_hash, options \\ []) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
options options
@ -432,8 +432,8 @@ defmodule Explorer.Chain do
@doc """ @doc """
Counts the number of `t:Explorer.Chain.Transaction.t/0` in the `block`. Counts the number of `t:Explorer.Chain.Transaction.t/0` in the `block`.
""" """
@spec block_to_transaction_count(Block.t()) :: non_neg_integer() @spec block_to_transaction_count(Hash.Full.t()) :: non_neg_integer()
def block_to_transaction_count(%Block{hash: block_hash}) do def block_to_transaction_count(block_hash) do
query = query =
from( from(
transaction in Transaction, transaction in Transaction,
@ -843,7 +843,7 @@ defmodule Explorer.Chain do
Returns `{:error, :not_found}` if there is no address by that hash present. Returns `{:error, :not_found}` if there is no address by that hash present.
Returns `{:error, :no_balance}` if there is no balance for that address at that block. Returns `{:error, :no_balance}` if there is no balance for that address at that block.
""" """
@spec get_balance_as_of_block(Hash.Address.t(), integer | :earliest | :latest | :pending) :: @spec get_balance_as_of_block(Hash.Address.t(), Block.block_number() | :earliest | :latest | :pending) ::
{:ok, Wei.t()} | {:error, :no_balance} | {:error, :not_found} {:ok, Wei.t()} | {:error, :no_balance} | {:error, :not_found}
def get_balance_as_of_block(address, block) when is_integer(block) do def get_balance_as_of_block(address, block) when is_integer(block) do
coin_balance_query = coin_balance_query =
@ -930,33 +930,44 @@ defmodule Explorer.Chain do
Repo.all(query) Repo.all(query)
end end
@spec find_contract_address(Hash.t()) :: {:ok, Address.t()} | {:error, :not_found} @doc """
def find_contract_address(%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash) do Finds an `t:Explorer.Chain.Address.t/0` that has the provided `t:Explorer.Chain.Address.t/0` `hash` and a contract.
## Options
* `:necessity_by_association` - use to load `t:association/0` as `:required` or `:optional`. If an association is
`:required`, and the `t:Explorer.Chain.Address.t/0` has no associated record for that association,
then the `t:Explorer.Chain.Address.t/0` will not be included in the list.
Optionally it also accepts a boolean to fetch the `has_decompiled_code?` virtual field or not
"""
@spec find_contract_address(Hash.Address.t(), [necessity_by_association_option], boolean()) ::
{:ok, Address.t()} | {:error, :not_found}
def find_contract_address(
%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash,
options \\ [],
query_decompiled_code_flag \\ false
) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
query = query =
from( from(
address in Address, address in Address,
preload: [
:contracts_creation_internal_transaction,
:names,
:smart_contract,
:token,
:contracts_creation_transaction
],
where: address.hash == ^hash and not is_nil(address.contract_code) where: address.hash == ^hash and not is_nil(address.contract_code)
) )
query_with_decompiled_flag = with_decompiled_code_flag(query, hash) query
|> join_associations(necessity_by_association)
address = Repo.one(query_with_decompiled_flag) |> with_decompiled_code_flag(hash, query_decompiled_code_flag)
|> Repo.one()
if address do |> case do
{:ok, address} nil -> {:error, :not_found}
else address -> {:ok, address}
{:error, :not_found}
end end
end end
@spec find_decompiled_contract_address(Hash.t()) :: {:ok, Address.t()} | {:error, :not_found} @spec find_decompiled_contract_address(Hash.Address.t()) :: {:ok, Address.t()} | {:error, :not_found}
def find_decompiled_contract_address(%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash) do def find_decompiled_contract_address(%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash) do
query = query =
from( from(
@ -1807,7 +1818,7 @@ defmodule Explorer.Chain do
Repo.one!(query) Repo.one!(query)
end end
def last_block_status do def last_db_block_status do
query = query =
from(block in Block, from(block in Block,
select: {block.number, block.timestamp}, select: {block.number, block.timestamp},
@ -1816,11 +1827,27 @@ defmodule Explorer.Chain do
limit: 1 limit: 1
) )
case Repo.one(query) do query
nil -> |> Repo.one()
{:error, :no_blocks} |> block_status()
end
{number, timestamp} -> def last_cache_block_status do
[
paging_options: %PagingOptions{page_size: 1}
]
|> list_blocks()
|> List.last()
|> case do
%{timestamp: timestamp, number: number} ->
block_status({number, timestamp})
_ ->
block_status(nil)
end
end
defp block_status({number, timestamp}) do
now = DateTime.utc_now() now = DateTime.utc_now()
last_block_period = DateTime.diff(now, timestamp, :millisecond) last_block_period = DateTime.diff(now, timestamp, :millisecond)
@ -1830,7 +1857,8 @@ defmodule Explorer.Chain do
{:ok, number, timestamp} {:ok, number, timestamp}
end end
end end
end
defp block_status(nil), do: {:error, :no_blocks}
@doc """ @doc """
Calculates the ranges of missing consensus blocks in `range`. Calculates the ranges of missing consensus blocks in `range`.
@ -2209,14 +2237,10 @@ defmodule Explorer.Chain do
""" """
@spec transaction_to_internal_transactions(Transaction.t(), [paging_options | necessity_by_association_option]) :: [ @spec transaction_to_internal_transactions(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [
InternalTransaction.t() InternalTransaction.t()
] ]
def transaction_to_internal_transactions( def transaction_to_internal_transactions(hash, options \\ []) when is_list(options) do
%Transaction{hash: %Hash{byte_count: unquote(Hash.Full.byte_count())} = hash},
options \\ []
)
when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options) paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@ -2244,12 +2268,8 @@ defmodule Explorer.Chain do
the `index` that are passed. the `index` that are passed.
""" """
@spec transaction_to_logs(Transaction.t(), [paging_options | necessity_by_association_option]) :: [Log.t()] @spec transaction_to_logs(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [Log.t()]
def transaction_to_logs( def transaction_to_logs(transaction_hash, options \\ []) when is_list(options) do
%Transaction{hash: %Hash{byte_count: unquote(Hash.Full.byte_count())} = transaction_hash},
options \\ []
)
when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options) paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@ -2276,14 +2296,10 @@ defmodule Explorer.Chain do
the `index` that are passed. the `index` that are passed.
""" """
@spec transaction_to_token_transfers(Transaction.t(), [paging_options | necessity_by_association_option]) :: [ @spec transaction_to_token_transfers(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [
TokenTransfer.t() TokenTransfer.t()
] ]
def transaction_to_token_transfers( def transaction_to_token_transfers(transaction_hash, options \\ []) when is_list(options) do
%Transaction{hash: %Hash{byte_count: unquote(Hash.Full.byte_count())} = transaction_hash},
options \\ []
)
when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options) paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@ -2510,16 +2526,16 @@ defmodule Explorer.Chain do
|> repo.insert(on_conflict: :nothing, conflict_target: [:address_hash, :name]) |> repo.insert(on_conflict: :nothing, conflict_target: [:address_hash, :name])
end end
@spec address_hash_to_address_with_source_code(%Explorer.Chain.Hash{}) :: %Explorer.Chain.Address{} | nil @spec address_hash_to_address_with_source_code(Hash.Address.t()) :: Address.t() | nil
def address_hash_to_address_with_source_code(%Explorer.Chain.Hash{} = address_hash) do def address_hash_to_address_with_source_code(address_hash) do
case Repo.get(Address, address_hash) do case Repo.get(Address, address_hash) do
nil -> nil nil -> nil
address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts]) address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts])
end end
end end
@spec address_hash_to_smart_contract(%Explorer.Chain.Hash{}) :: %Explorer.Chain.SmartContract{} | nil @spec address_hash_to_smart_contract(Hash.Address.t()) :: SmartContract.t() | nil
def address_hash_to_smart_contract(%Explorer.Chain.Hash{} = address_hash) do def address_hash_to_smart_contract(address_hash) do
query = query =
from( from(
smart_contract in SmartContract, smart_contract in SmartContract,
@ -3276,8 +3292,6 @@ defmodule Explorer.Chain do
defp staking_pool_filter(query, _), do: query defp staking_pool_filter(query, _), do: query
defp with_decompiled_code_flag(query, hash, use_option \\ true)
defp with_decompiled_code_flag(query, _hash, false), do: query defp with_decompiled_code_flag(query, _hash, false), do: query
defp with_decompiled_code_flag(query, hash, true) do defp with_decompiled_code_flag(query, hash, true) do
@ -3300,4 +3314,203 @@ defmodule Explorer.Chain do
|> Base.decode16!(case: :mixed) |> Base.decode16!(case: :mixed)
|> TypeDecoder.decode_raw(types) |> TypeDecoder.decode_raw(types)
end end
@doc """
Checks if an `t:Explorer.Chain.Address.t/0` with the given `hash` exists.
Returns `:ok` if found
iex> {:ok, %Explorer.Chain.Address{hash: hash}} = Explorer.Chain.create_address(
...> %{hash: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"}
...> )
iex> Explorer.Chain.check_address_exists(hash)
:ok
Returns `:not_found` if not found
iex> {:ok, hash} = Explorer.Chain.string_to_address_hash("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")
iex> Explorer.Chain.check_address_exists(hash)
:not_found
"""
@spec check_address_exists(Hash.Address.t()) :: :ok | :not_found
def check_address_exists(address_hash) do
address_hash
|> address_exists?()
|> boolean_to_check_result()
end
@doc """
Checks if an `t:Explorer.Chain.Address.t/0` with the given `hash` exists.
Returns `true` if found
iex> {:ok, %Explorer.Chain.Address{hash: hash}} = Explorer.Chain.create_address(
...> %{hash: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"}
...> )
iex> Explorer.Chain.address_exists?(hash)
true
Returns `false` if not found
iex> {:ok, hash} = Explorer.Chain.string_to_address_hash("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")
iex> Explorer.Chain.address_exists?(hash)
false
"""
@spec address_exists?(Hash.Address.t()) :: boolean()
def address_exists?(address_hash) do
query =
from(
address in Address,
where: address.hash == ^address_hash
)
Repo.exists?(query)
end
@doc """
Checks if it exists an `t:Explorer.Chain.Address.t/0` that has the provided
`t:Explorer.Chain.Address.t/0` `hash` and a contract.
Returns `:ok` if found and `:not_found` otherwise.
"""
@spec check_contract_address_exists(Hash.Address.t()) :: :ok | :not_found
def check_contract_address_exists(address_hash) do
address_hash
|> contract_address_exists?()
|> boolean_to_check_result()
end
@doc """
Checks if it exists an `t:Explorer.Chain.Address.t/0` that has the provided
`t:Explorer.Chain.Address.t/0` `hash` and a contract.
Returns `true` if found and `false` otherwise.
"""
@spec contract_address_exists?(Hash.Address.t()) :: boolean()
def contract_address_exists?(address_hash) do
query =
from(
address in Address,
where: address.hash == ^address_hash and not is_nil(address.contract_code)
)
Repo.exists?(query)
end
@doc """
Checks if it exists a `t:Explorer.Chain.DecompiledSmartContract.t/0` for the
`t:Explorer.Chain.Address.t/0` with the provided `hash` and with the provided version.
Returns `:ok` if found and `:not_found` otherwise.
"""
@spec check_decompiled_contract_exists(Hash.Address.t(), String.t()) :: :ok | :not_found
def check_decompiled_contract_exists(address_hash, version) do
address_hash
|> decompiled_contract_exists?(version)
|> boolean_to_check_result()
end
@doc """
Checks if it exists a `t:Explorer.Chain.DecompiledSmartContract.t/0` for the
`t:Explorer.Chain.Address.t/0` with the provided `hash` and with the provided version.
Returns `true` if found and `false` otherwise.
"""
@spec decompiled_contract_exists?(Hash.Address.t(), String.t()) :: boolean()
def decompiled_contract_exists?(address_hash, version) do
query =
from(contract in DecompiledSmartContract,
where: contract.address_hash == ^address_hash and contract.decompiler_version == ^version
)
Repo.exists?(query)
end
@doc """
Checks if it exists a verified `t:Explorer.Chain.SmartContract.t/0` for the
`t:Explorer.Chain.Address.t/0` with the provided `hash`.
Returns `:ok` if found and `:not_found` otherwise.
"""
@spec check_verified_smart_contract_exists(Hash.Address.t()) :: :ok | :not_found
def check_verified_smart_contract_exists(address_hash) do
address_hash
|> verified_smart_contract_exists?()
|> boolean_to_check_result()
end
@doc """
Checks if it exists a verified `t:Explorer.Chain.SmartContract.t/0` for the
`t:Explorer.Chain.Address.t/0` with the provided `hash`.
Returns `true` if found and `false` otherwise.
"""
@spec verified_smart_contract_exists?(Hash.Address.t()) :: boolean()
def verified_smart_contract_exists?(address_hash) do
query =
from(
smart_contract in SmartContract,
where: smart_contract.address_hash == ^address_hash
)
Repo.exists?(query)
end
@doc """
Checks if a `t:Explorer.Chain.Transaction.t/0` with the given `hash` exists.
Returns `:ok` if found
iex> %Transaction{hash: hash} = insert(:transaction)
iex> Explorer.Chain.check_transaction_exists(hash)
:ok
Returns `:not_found` if not found
iex> {:ok, hash} = Explorer.Chain.string_to_transaction_hash(
...> "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b"
...> )
iex> Explorer.Chain.check_transaction_exists(hash)
:not_found
"""
@spec check_transaction_exists(Hash.Full.t()) :: :ok | :not_found
def check_transaction_exists(hash) do
hash
|> transaction_exists?()
|> boolean_to_check_result()
end
@doc """
Checks if a `t:Explorer.Chain.Transaction.t/0` with the given `hash` exists.
Returns `true` if found
iex> %Transaction{hash: hash} = insert(:transaction)
iex> Explorer.Chain.transaction_exists?(hash)
true
Returns `false` if not found
iex> {:ok, hash} = Explorer.Chain.string_to_transaction_hash(
...> "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b"
...> )
iex> Explorer.Chain.transaction_exists?(hash)
false
"""
@spec transaction_exists?(Hash.Full.t()) :: boolean()
def transaction_exists?(hash) do
query =
from(
transaction in Transaction,
where: transaction.hash == ^hash
)
Repo.exists?(query)
end
defp boolean_to_check_result(true), do: :ok
defp boolean_to_check_result(false), do: :not_found
end end

@ -392,7 +392,7 @@ defmodule Explorer.Chain.InternalTransaction do
@create_required_fields ~w(from_address_hash gas index init trace_address transaction_hash value)a @create_required_fields ~w(from_address_hash gas index init trace_address transaction_hash value)a
@create_allowed_fields @create_optional_fields ++ @create_required_fields @create_allowed_fields @create_optional_fields ++ @create_required_fields
defp type_changeset(changeset, attrs, :create) do defp type_changeset(changeset, attrs, type) when type in [:create, :create2] do
changeset changeset
|> cast(attrs, @create_allowed_fields) |> cast(attrs, @create_allowed_fields)
|> validate_required(@create_required_fields) |> validate_required(@create_required_fields)
@ -537,7 +537,7 @@ defmodule Explorer.Chain.InternalTransaction do
|> put_raw_call_error_or_result(transaction) |> put_raw_call_error_or_result(transaction)
end end
defp internal_transaction_to_raw(%{type: :create} = transaction) do defp internal_transaction_to_raw(%{type: type} = transaction) when type in [:create, :create2] do
%{ %{
from_address_hash: from_address_hash, from_address_hash: from_address_hash,
gas: gas, gas: gas,
@ -549,7 +549,7 @@ defmodule Explorer.Chain.InternalTransaction do
action = %{"from" => from_address_hash, "gas" => gas, "init" => init, "value" => value} action = %{"from" => from_address_hash, "gas" => gas, "init" => init, "value" => value}
%{ %{
"type" => "create", "type" => Atom.to_string(type),
"action" => Action.to_raw(action), "action" => Action.to_raw(action),
"traceAddress" => trace_address "traceAddress" => trace_address
} }

@ -11,7 +11,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
* `:reward` * `:reward`
* `:selfdestruct` * `:selfdestruct`
""" """
@type t :: :call | :create | :reward | :selfdestruct @type t :: :call | :create | :create2 | :reward | :selfdestruct
@doc """ @doc """
Casts `term` to `t:t/0` Casts `term` to `t:t/0`
@ -22,6 +22,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call} {:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast(:create) iex> Explorer.Chain.InternalTransaction.Type.cast(:create)
{:ok, :create} {:ok, :create}
iex> Explorer.Chain.InternalTransaction.Type.cast(:create2)
{:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast(:reward) iex> Explorer.Chain.InternalTransaction.Type.cast(:reward)
{:ok, :reward} {:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast(:selfdestruct) iex> Explorer.Chain.InternalTransaction.Type.cast(:selfdestruct)
@ -33,6 +35,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call} {:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast("create") iex> Explorer.Chain.InternalTransaction.Type.cast("create")
{:ok, :create} {:ok, :create}
iex> Explorer.Chain.InternalTransaction.Type.cast("create2")
{:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast("reward") iex> Explorer.Chain.InternalTransaction.Type.cast("reward")
{:ok, :reward} {:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast("selfdestruct") iex> Explorer.Chain.InternalTransaction.Type.cast("selfdestruct")
@ -53,9 +57,10 @@ defmodule Explorer.Chain.InternalTransaction.Type do
""" """
@impl Ecto.Type @impl Ecto.Type
@spec cast(term()) :: {:ok, t()} | :error @spec cast(term()) :: {:ok, t()} | :error
def cast(t) when t in ~w(call create selfdestruct reward)a, do: {:ok, t} def cast(t) when t in ~w(call create create2 selfdestruct reward)a, do: {:ok, t}
def cast("call"), do: {:ok, :call} def cast("call"), do: {:ok, :call}
def cast("create"), do: {:ok, :create} def cast("create"), do: {:ok, :create}
def cast("create2"), do: {:ok, :create2}
def cast("reward"), do: {:ok, :reward} def cast("reward"), do: {:ok, :reward}
def cast("selfdestruct"), do: {:ok, :selfdestruct} def cast("selfdestruct"), do: {:ok, :selfdestruct}
def cast(_), do: :error def cast(_), do: :error
@ -67,6 +72,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, "call"} {:ok, "call"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:create) iex> Explorer.Chain.InternalTransaction.Type.dump(:create)
{:ok, "create"} {:ok, "create"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:create2)
{:ok, "create2"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:reward) iex> Explorer.Chain.InternalTransaction.Type.dump(:reward)
{:ok, "reward"} {:ok, "reward"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:selfdestruct) iex> Explorer.Chain.InternalTransaction.Type.dump(:selfdestruct)
@ -87,6 +94,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec dump(term()) :: {:ok, String.t()} | :error @spec dump(term()) :: {:ok, String.t()} | :error
def dump(:call), do: {:ok, "call"} def dump(:call), do: {:ok, "call"}
def dump(:create), do: {:ok, "create"} def dump(:create), do: {:ok, "create"}
def dump(:create2), do: {:ok, "create2"}
def dump(:reward), do: {:ok, "reward"} def dump(:reward), do: {:ok, "reward"}
def dump(:selfdestruct), do: {:ok, "selfdestruct"} def dump(:selfdestruct), do: {:ok, "selfdestruct"}
def dump(_), do: :error def dump(_), do: :error
@ -98,6 +106,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call} {:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.load("create") iex> Explorer.Chain.InternalTransaction.Type.load("create")
{:ok, :create} {:ok, :create}
iex> Explorer.Chain.InternalTransaction.Type.load("create2")
{:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.load("reward") iex> Explorer.Chain.InternalTransaction.Type.load("reward")
{:ok, :reward} {:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.load("selfdestruct") iex> Explorer.Chain.InternalTransaction.Type.load("selfdestruct")
@ -118,6 +128,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec load(term()) :: {:ok, t()} | :error @spec load(term()) :: {:ok, t()} | :error
def load("call"), do: {:ok, :call} def load("call"), do: {:ok, :call}
def load("create"), do: {:ok, :create} def load("create"), do: {:ok, :create}
def load("create2"), do: {:ok, :create2}
def load("reward"), do: {:ok, :reward} def load("reward"), do: {:ok, :reward}
def load("selfdestruct"), do: {:ok, :selfdestruct} def load("selfdestruct"), do: {:ok, :selfdestruct}
# deprecated # deprecated

@ -11,7 +11,7 @@ defmodule Explorer.Counters.AverageBlockTime do
alias Explorer.Repo alias Explorer.Repo
alias Timex.Duration alias Timex.Duration
@refresh_period 30 * 60 * 1_000 @refresh_period Application.get_env(:explorer, __MODULE__)[:period]
@doc """ @doc """
Starts a process to periodically update the counter of the token holders. Starts a process to periodically update the counter of the token holders.

@ -12,7 +12,7 @@ defmodule Explorer.Market.MarketHistoryCache do
@last_update_key :last_update @last_update_key :last_update
@history_key :history @history_key :history
# 6 hours # 6 hours
@cache_period 1_000 * 60 * 60 * 6 @cache_period Application.get_env(:explorer, __MODULE__)[:period]
@recent_days 30 @recent_days 30
def fetch do def fetch do

@ -8,7 +8,7 @@ defmodule Explorer.SmartContract.Reader do
alias EthereumJSONRPC.Contract alias EthereumJSONRPC.Contract
alias Explorer.Chain alias Explorer.Chain
alias Explorer.Chain.Hash alias Explorer.Chain.{Hash, SmartContract}
@typedoc """ @typedoc """
Map of functions to call with the values for the function to be called with. Map of functions to call with the values for the function to be called with.
@ -34,6 +34,8 @@ defmodule Explorer.SmartContract.Reader do
@doc """ @doc """
Queries the contract functions on the blockchain and returns the call results. Queries the contract functions on the blockchain and returns the call results.
Optionally accepts the abi if it has already been fetched.
## Examples ## Examples
Note that for this example to work the database must be up to date with the Note that for this example to work the database must be up to date with the
@ -57,15 +59,21 @@ defmodule Explorer.SmartContract.Reader do
) )
# => %{"sum" => {:error, "Data overflow encoding int, data `abc` cannot fit in 256 bits"}} # => %{"sum" => {:error, "Data overflow encoding int, data `abc` cannot fit in 256 bits"}}
""" """
@spec query_verified_contract(Hash.Address.t(), functions()) :: functions_results() @spec query_verified_contract(Hash.Address.t(), functions(), SmartContract.abi() | nil) :: functions_results()
def query_verified_contract(address_hash, functions) do def query_verified_contract(address_hash, functions, mabi \\ nil) do
contract_address = Hash.to_string(address_hash) contract_address = Hash.to_string(address_hash)
abi = abi =
case mabi do
nil ->
address_hash address_hash
|> Chain.address_hash_to_smart_contract() |> Chain.address_hash_to_smart_contract()
|> Map.get(:abi) |> Map.get(:abi)
_ ->
mabi
end
query_contract(contract_address, abi, functions) query_contract(contract_address, abi, functions)
end end
@ -156,41 +164,41 @@ defmodule Explorer.SmartContract.Reader do
""" """
@spec read_only_functions(Hash.t()) :: [%{}] @spec read_only_functions(Hash.t()) :: [%{}]
def read_only_functions(contract_address_hash) do def read_only_functions(contract_address_hash) do
abi =
contract_address_hash contract_address_hash
|> Chain.address_hash_to_smart_contract() |> Chain.address_hash_to_smart_contract()
|> Map.get(:abi, []) |> Map.get(:abi)
case abi do
nil ->
[]
_ ->
abi
|> Enum.filter(& &1["constant"]) |> Enum.filter(& &1["constant"])
|> fetch_current_value_from_blockchain(contract_address_hash, []) |> Enum.map(&fetch_current_value_from_blockchain(&1, abi, contract_address_hash))
|> Enum.reverse() end
end end
def fetch_current_value_from_blockchain( defp fetch_current_value_from_blockchain(function, abi, contract_address_hash) do
[%{"inputs" => []} = function | tail],
contract_address_hash,
acc
) do
values = values =
fetch_from_blockchain(contract_address_hash, %{ case function do
name: function["name"], %{"inputs" => []} ->
args: function["inputs"], name = function["name"]
outputs: function["outputs"] args = function["inputs"]
}) outputs = function["outputs"]
formatted = Map.replace!(function, "outputs", values) contract_address_hash
|> query_verified_contract(%{name => normalize_args(args)}, abi)
|> link_outputs_and_values(outputs, name)
fetch_current_value_from_blockchain(tail, contract_address_hash, [formatted | acc]) _ ->
link_outputs_and_values(%{}, Map.get(function, "outputs", []), function["name"])
end end
def fetch_current_value_from_blockchain([function | tail], contract_address_hash, acc) do Map.replace!(function, "outputs", values)
values = link_outputs_and_values(%{}, Map.get(function, "outputs", []), function["name"])
formatted = Map.replace!(function, "outputs", values)
fetch_current_value_from_blockchain(tail, contract_address_hash, [formatted | acc])
end end
def fetch_current_value_from_blockchain([], _contract_address_hash, acc), do: acc
@doc """ @doc """
Fetches the blockchain value of a function that requires arguments. Fetches the blockchain value of a function that requires arguments.
""" """
@ -201,23 +209,27 @@ defmodule Explorer.SmartContract.Reader do
@spec query_function(Hash.t(), %{name: String.t(), args: [term()]}) :: [%{}] @spec query_function(Hash.t(), %{name: String.t(), args: [term()]}) :: [%{}]
def query_function(contract_address_hash, %{name: name, args: args}) do def query_function(contract_address_hash, %{name: name, args: args}) do
function = abi =
contract_address_hash contract_address_hash
|> Chain.address_hash_to_smart_contract() |> Chain.address_hash_to_smart_contract()
|> Map.get(:abi, []) |> Map.get(:abi)
outputs =
case abi do
nil ->
nil
_ ->
function =
abi
|> Enum.filter(fn function -> function["name"] == name end) |> Enum.filter(fn function -> function["name"] == name end)
|> List.first() |> List.first()
fetch_from_blockchain(contract_address_hash, %{ function["outputs"]
name: name,
args: args,
outputs: function["outputs"]
})
end end
defp fetch_from_blockchain(contract_address_hash, %{name: name, args: args, outputs: outputs}) do
contract_address_hash contract_address_hash
|> query_verified_contract(%{name => normalize_args(args)}) |> query_verified_contract(%{name => normalize_args(args)}, abi)
|> link_outputs_and_values(outputs, name) |> link_outputs_and_values(outputs, name)
end end

@ -117,7 +117,7 @@ defmodule Explorer.Mixfile do
# Attach `:prometheus_ecto` to `:ecto` # Attach `:prometheus_ecto` to `:ecto`
{:telemetry, "~> 0.3.0"}, {:telemetry, "~> 0.3.0"},
# `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0` # `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0`
{:timex, "~> 3.4"}, {:timex, "~> 3.6"},
{:con_cache, "~> 0.13"} {:con_cache, "~> 0.13"}
] ]
end end

@ -50,21 +50,35 @@ defmodule Explorer.ChainTest do
end end
end end
describe "last_block_status/0" do describe "last_db_block_status/0" do
test "return no_blocks errors if db is empty" do test "return no_blocks errors if db is empty" do
assert {:error, :no_blocks} = Chain.last_block_status() assert {:error, :no_blocks} = Chain.last_db_block_status()
end end
test "returns {:ok, last_block_period} if block is in healthy period" do test "returns {:ok, last_block_period} if block is in healthy period" do
insert(:block, consensus: true) insert(:block, consensus: true)
assert {:ok, _, _} = Chain.last_block_status() assert {:ok, _, _} = Chain.last_db_block_status()
end end
test "return {:ok, last_block_period} if block is not in healthy period" do test "return {:ok, last_block_period} if block is not in healthy period" do
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
assert {:error, _, _} = Chain.last_block_status() assert {:error, _, _} = Chain.last_db_block_status()
end
end
describe "last_cache_block_status/0" do
test "returns success if cache is not stale" do
insert(:block, consensus: true)
assert {:ok, _, _} = Chain.last_cache_block_status()
end
test "return error if cache is stale" do
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
assert {:error, _, _} = Chain.last_cache_block_status()
end end
end end
@ -630,7 +644,7 @@ defmodule Explorer.ChainTest do
assert Repo.aggregate(Transaction, :count, :hash) == 0 assert Repo.aggregate(Transaction, :count, :hash) == 0
assert [] = Chain.block_to_transactions(block) assert [] = Chain.block_to_transactions(block.hash)
end end
test "with transactions" do test "with transactions" do
@ -639,7 +653,7 @@ defmodule Explorer.ChainTest do
|> insert() |> insert()
|> with_block() |> with_block()
assert [%Transaction{hash: ^transaction_hash}] = Chain.block_to_transactions(block) assert [%Transaction{hash: ^transaction_hash}] = Chain.block_to_transactions(block.hash)
end end
test "with transactions can be paginated by {index}" do test "with transactions can be paginated by {index}" do
@ -657,7 +671,7 @@ defmodule Explorer.ChainTest do
|> with_block(block) |> with_block(block)
assert second_page_hashes == assert second_page_hashes ==
block block.hash
|> Chain.block_to_transactions(paging_options: %PagingOptions{key: {index}, page_size: 50}) |> Chain.block_to_transactions(paging_options: %PagingOptions{key: {index}, page_size: 50})
|> Enum.map(& &1.hash) |> Enum.map(& &1.hash)
|> Enum.reverse() |> Enum.reverse()
@ -683,7 +697,7 @@ defmodule Explorer.ChainTest do
token: token token: token
) )
fetched_transaction = List.first(Explorer.Chain.block_to_transactions(block)) fetched_transaction = List.first(Explorer.Chain.block_to_transactions(block.hash))
assert fetched_transaction.hash == transaction.hash assert fetched_transaction.hash == transaction.hash
assert length(fetched_transaction.token_transfers) == 2 assert length(fetched_transaction.token_transfers) == 2
end end
@ -693,7 +707,7 @@ defmodule Explorer.ChainTest do
test "without transactions" do test "without transactions" do
block = insert(:block) block = insert(:block)
assert Chain.block_to_transaction_count(block) == 0 assert Chain.block_to_transaction_count(block.hash) == 0
end end
test "with transactions" do test "with transactions" do
@ -702,7 +716,7 @@ defmodule Explorer.ChainTest do
|> insert() |> insert()
|> with_block() |> with_block()
assert Chain.block_to_transaction_count(block) == 1 assert Chain.block_to_transaction_count(block.hash) == 1
end end
end end
@ -2090,7 +2104,7 @@ defmodule Explorer.ChainTest do
test "with transaction without internal transactions" do test "with transaction without internal transactions" do
transaction = insert(:transaction) transaction = insert(:transaction)
assert [] = Chain.transaction_to_internal_transactions(transaction) assert [] = Chain.transaction_to_internal_transactions(transaction.hash)
end end
test "with transaction with internal transactions returns all internal transactions for a given transaction hash" do test "with transaction with internal transactions returns all internal transactions for a given transaction hash" do
@ -2117,7 +2131,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index transaction_index: transaction.index
) )
results = [internal_transaction | _] = Chain.transaction_to_internal_transactions(transaction) results = [internal_transaction | _] = Chain.transaction_to_internal_transactions(transaction.hash)
assert 2 == length(results) assert 2 == length(results)
@ -2151,7 +2165,7 @@ defmodule Explorer.ChainTest do
to_address: %Ecto.Association.NotLoaded{}, to_address: %Ecto.Association.NotLoaded{},
transaction: %Transaction{block: %Ecto.Association.NotLoaded{}} transaction: %Transaction{block: %Ecto.Association.NotLoaded{}}
} }
] = Chain.transaction_to_internal_transactions(transaction) ] = Chain.transaction_to_internal_transactions(transaction.hash)
assert [ assert [
%InternalTransaction{ %InternalTransaction{
@ -2161,7 +2175,7 @@ defmodule Explorer.ChainTest do
} }
] = ] =
Chain.transaction_to_internal_transactions( Chain.transaction_to_internal_transactions(
transaction, transaction.hash,
necessity_by_association: %{ necessity_by_association: %{
:from_address => :optional, :from_address => :optional,
:to_address => :optional, :to_address => :optional,
@ -2183,7 +2197,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index transaction_index: transaction.index
) )
result = Chain.transaction_to_internal_transactions(transaction) result = Chain.transaction_to_internal_transactions(transaction.hash)
assert Enum.empty?(result) assert Enum.empty?(result)
end end
@ -2202,7 +2216,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index transaction_index: transaction.index
) )
actual = Enum.at(Chain.transaction_to_internal_transactions(transaction), 0) actual = Enum.at(Chain.transaction_to_internal_transactions(transaction.hash), 0)
assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index} assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index}
end end
@ -2222,7 +2236,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index transaction_index: transaction.index
) )
actual = Enum.at(Chain.transaction_to_internal_transactions(transaction), 0) actual = Enum.at(Chain.transaction_to_internal_transactions(transaction.hash), 0)
assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index} assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index}
end end
@ -2243,7 +2257,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index transaction_index: transaction.index
) )
actual = Enum.at(Chain.transaction_to_internal_transactions(transaction), 0) actual = Enum.at(Chain.transaction_to_internal_transactions(transaction.hash), 0)
assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index} assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index}
end end
@ -2271,7 +2285,7 @@ defmodule Explorer.ChainTest do
) )
result = result =
transaction transaction.hash
|> Chain.transaction_to_internal_transactions() |> Chain.transaction_to_internal_transactions()
|> Enum.map(&{&1.transaction_hash, &1.index}) |> Enum.map(&{&1.transaction_hash, &1.index})
@ -2301,17 +2315,17 @@ defmodule Explorer.ChainTest do
) )
assert [{first_transaction_hash, first_index}, {second_transaction_hash, second_index}] == assert [{first_transaction_hash, first_index}, {second_transaction_hash, second_index}] ==
transaction transaction.hash
|> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {-1}, page_size: 2}) |> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {-1}, page_size: 2})
|> Enum.map(&{&1.transaction_hash, &1.index}) |> Enum.map(&{&1.transaction_hash, &1.index})
assert [{first_transaction_hash, first_index}] == assert [{first_transaction_hash, first_index}] ==
transaction transaction.hash
|> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {-1}, page_size: 1}) |> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {-1}, page_size: 1})
|> Enum.map(&{&1.transaction_hash, &1.index}) |> Enum.map(&{&1.transaction_hash, &1.index})
assert [{second_transaction_hash, second_index}] == assert [{second_transaction_hash, second_index}] ==
transaction transaction.hash
|> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {0}, page_size: 2}) |> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {0}, page_size: 2})
|> Enum.map(&{&1.transaction_hash, &1.index}) |> Enum.map(&{&1.transaction_hash, &1.index})
end end
@ -2321,7 +2335,7 @@ defmodule Explorer.ChainTest do
test "without logs" do test "without logs" do
transaction = insert(:transaction) transaction = insert(:transaction)
assert [] = Chain.transaction_to_logs(transaction) assert [] = Chain.transaction_to_logs(transaction.hash)
end end
test "with logs" do test "with logs" do
@ -2332,7 +2346,7 @@ defmodule Explorer.ChainTest do
%Log{transaction_hash: transaction_hash, index: index} = insert(:log, transaction: transaction) %Log{transaction_hash: transaction_hash, index: index} = insert(:log, transaction: transaction)
assert [%Log{transaction_hash: ^transaction_hash, index: ^index}] = Chain.transaction_to_logs(transaction) assert [%Log{transaction_hash: ^transaction_hash, index: ^index}] = Chain.transaction_to_logs(transaction.hash)
end end
test "with logs can be paginated" do test "with logs can be paginated" do
@ -2349,7 +2363,7 @@ defmodule Explorer.ChainTest do
|> Enum.map(& &1.index) |> Enum.map(& &1.index)
assert second_page_indexes == assert second_page_indexes ==
transaction transaction.hash
|> Chain.transaction_to_logs(paging_options: %PagingOptions{key: {log.index}, page_size: 50}) |> Chain.transaction_to_logs(paging_options: %PagingOptions{key: {log.index}, page_size: 50})
|> Enum.map(& &1.index) |> Enum.map(& &1.index)
end end
@ -2364,7 +2378,7 @@ defmodule Explorer.ChainTest do
assert [%Log{address: %Address{}, transaction: %Transaction{}}] = assert [%Log{address: %Address{}, transaction: %Transaction{}}] =
Chain.transaction_to_logs( Chain.transaction_to_logs(
transaction, transaction.hash,
necessity_by_association: %{ necessity_by_association: %{
address: :optional, address: :optional,
transaction: :optional transaction: :optional
@ -2376,7 +2390,7 @@ defmodule Explorer.ChainTest do
address: %Ecto.Association.NotLoaded{}, address: %Ecto.Association.NotLoaded{},
transaction: %Ecto.Association.NotLoaded{} transaction: %Ecto.Association.NotLoaded{}
} }
] = Chain.transaction_to_logs(transaction) ] = Chain.transaction_to_logs(transaction.hash)
end end
end end
@ -2384,7 +2398,7 @@ defmodule Explorer.ChainTest do
test "without token transfers" do test "without token transfers" do
transaction = insert(:transaction) transaction = insert(:transaction)
assert [] = Chain.transaction_to_token_transfers(transaction) assert [] = Chain.transaction_to_token_transfers(transaction.hash)
end end
test "with token transfers" do test "with token transfers" do
@ -2397,7 +2411,7 @@ defmodule Explorer.ChainTest do
insert(:token_transfer, transaction: transaction) insert(:token_transfer, transaction: transaction)
assert [%TokenTransfer{transaction_hash: ^transaction_hash, log_index: ^log_index}] = assert [%TokenTransfer{transaction_hash: ^transaction_hash, log_index: ^log_index}] =
Chain.transaction_to_token_transfers(transaction) Chain.transaction_to_token_transfers(transaction.hash)
end end
test "token transfers necessity_by_association loads associations" do test "token transfers necessity_by_association loads associations" do
@ -2410,7 +2424,7 @@ defmodule Explorer.ChainTest do
assert [%TokenTransfer{token: %Token{}, transaction: %Transaction{}}] = assert [%TokenTransfer{token: %Token{}, transaction: %Transaction{}}] =
Chain.transaction_to_token_transfers( Chain.transaction_to_token_transfers(
transaction, transaction.hash,
necessity_by_association: %{ necessity_by_association: %{
token: :optional, token: :optional,
transaction: :optional transaction: :optional
@ -2422,7 +2436,7 @@ defmodule Explorer.ChainTest do
token: %Ecto.Association.NotLoaded{}, token: %Ecto.Association.NotLoaded{},
transaction: %Ecto.Association.NotLoaded{} transaction: %Ecto.Association.NotLoaded{}
} }
] = Chain.transaction_to_token_transfers(transaction) ] = Chain.transaction_to_token_transfers(transaction.hash)
end end
end end
@ -2480,7 +2494,17 @@ defmodule Explorer.ChainTest do
insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil, names: []) insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil, names: [])
|> Repo.preload([:contracts_creation_internal_transaction, :contracts_creation_transaction, :token]) |> Repo.preload([:contracts_creation_internal_transaction, :contracts_creation_transaction, :token])
response = Chain.find_contract_address(address.hash) options = [
necessity_by_association: %{
:contracts_creation_internal_transaction => :optional,
:names => :optional,
:smart_contract => :optional,
:token => :optional,
:contracts_creation_transaction => :optional
}
]
response = Chain.find_contract_address(address.hash, options, true)
assert response == {:ok, address} assert response == {:ok, address}
end end
@ -2523,11 +2547,11 @@ defmodule Explorer.ChainTest do
|> Decimal.add(Decimal.new(3)) |> Decimal.add(Decimal.new(3))
|> Wei.from(:wei) |> Wei.from(:wei)
assert expected == Chain.block_reward(block) assert expected == Chain.block_reward(block.number)
end end
test "with block without transactions", %{block: block, emission_reward: emission_reward} do test "with block without transactions", %{block: block, emission_reward: emission_reward} do
assert emission_reward.reward == Chain.block_reward(block) assert emission_reward.reward == Chain.block_reward(block.number)
end end
end end

@ -102,7 +102,7 @@ defmodule Explorer.SmartContract.ReaderTest do
end end
end end
describe "query_verified_contract/2" do describe "query_verified_contract/3" do
test "correctly returns the results of the smart contract functions" do test "correctly returns the results of the smart contract functions" do
hash = hash =
:smart_contract :smart_contract

@ -2,9 +2,11 @@
rm -rf ./_build rm -rf ./_build
rm -rf ./deps rm -rf ./deps
rm -rf ./logs/dev logs=$(find . -not -path '*/\.*' -name "logs" -type d)
rm -rf ./apps/explorer/node_modules dev=$(find ${logs} -name "dev")
rm -rf ./apps/block_scout_web/assets/node_modules rm -rf {ls -la ${dev}}
find . -name "node_modules" -type d -exec rm -rf '{}' +
case "$1" in case "$1" in
-f) -f)

Loading…
Cancel
Save