Merge branch 'master' into ab-remove-outer-tables-for-decoded-data

pull/2413/head
Ayrat Badykov 5 years ago committed by GitHub
commit be5ae59572
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      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. 46
      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. 19
      apps/block_scout_web/assets/js/lib/market_history_chart.js
  22. 11
      apps/block_scout_web/assets/js/pages/dark-mode-switcher.js
  23. 6
      apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex
  24. 12
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex
  25. 10
      apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
  26. 12
      apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
  27. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
  28. 5
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
  29. 2
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
  30. 21
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller.ex
  31. 21
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex
  32. 4
      apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
  33. 14
      apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
  34. 6
      apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
  35. 6
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
  36. 8
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex
  37. 2
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex
  38. 2
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex
  39. 9
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex
  40. 2
      apps/block_scout_web/lib/block_scout_web/router.ex
  41. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
  42. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
  43. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
  44. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex
  45. 70
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
  46. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
  47. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
  48. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex
  49. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
  50. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex
  51. 4
      apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex
  52. 4
      apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
  53. 8
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  54. 85
      apps/block_scout_web/lib/block_scout_web/templates/common_components/_table-loader.html.eex
  55. 72
      apps/block_scout_web/lib/block_scout_web/templates/common_components/_tile-loader.html.eex
  56. 35
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  57. 5
      apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
  58. 9
      apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
  59. 4
      apps/block_scout_web/lib/block_scout_web/templates/tokens/holder/index.html.eex
  60. 4
      apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex
  61. 4
      apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex
  62. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
  63. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
  64. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
  65. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
  66. 6
      apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
  67. 105
      apps/block_scout_web/priv/gettext/default.pot
  68. 103
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  69. 4
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex
  70. 10
      apps/ethereum_jsonrpc/test/ethereum_jsonrpc/transaction_test.exs
  71. 296
      apps/explorer/lib/explorer/chain.ex
  72. 82
      apps/explorer/lib/explorer/smart_contract/reader.ex
  73. 70
      apps/explorer/test/explorer/chain_test.exs
  74. 2
      apps/explorer/test/explorer/smart_contract/reader_test.exs

@ -1,6 +1,9 @@
## Current ## Current
### Features ### 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 - [#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 - [#2366](https://github.com/poanetwork/blockscout/pull/2366) - paginate eth logs
@ -11,10 +14,13 @@
### Fixes ### Fixes
- [#2413](https://github.com/poanetwork/blockscout/pull/2413) - remove outer tables for decoded data - [#2413](https://github.com/poanetwork/blockscout/pull/2413) - remove outer tables for decoded data
- [#2416](https://github.com/poanetwork/blockscout/pull/2416) - Fix "page not found" handling in the router
- [#2410](https://github.com/poanetwork/blockscout/pull/2410) - preload smart contract for logs decoding - [#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 - [#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)
- [#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
@ -32,6 +38,7 @@
- [#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
- [#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 - [#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

@ -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%;

@ -349,6 +349,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'

@ -88,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 = {
@ -96,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 = {
@ -106,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

@ -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

@ -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",

@ -130,6 +130,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 +151,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

@ -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)

@ -24,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>

@ -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 %>

@ -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 %>

@ -117,13 +117,7 @@
<%= gettext "Something went wrong, click to retry." %> <%= gettext "Something went wrong, click to retry." %>
</span> </span>
</button> </button>
<div hidden data-selector="loading-message" class="tile tile-muted text-center mt-3"> <%= 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>
</span> </span>
</div> </div>
</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 %>

@ -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>

@ -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,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

@ -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,13 +178,13 @@ 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 ""
@ -328,13 +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: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 #, 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
@ -376,7 +369,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 +393,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 +447,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 +479,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 +500,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,6 +548,7 @@ 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:19 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
@ -604,7 +598,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,7 +616,7 @@ 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 ""
@ -669,8 +663,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 +768,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,11 +819,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:85
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
@ -873,7 +862,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 +889,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 +904,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 ""
@ -1058,7 +1047,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 +1057,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,27 +1117,18 @@ 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
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
msgid "Indexed?"
msgstr ""
#, elixir-format
#: 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 ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
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 ""
@ -1166,12 +1140,14 @@ 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,21 +1163,6 @@ msgstr ""
msgid "Error rendering value" msgid "Error rendering value"
msgstr "" msgstr ""
#, elixir-format
#: 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/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:43
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
@ -1273,7 +1234,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 ""
@ -1479,8 +1440,8 @@ 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 ""
@ -1706,7 +1667,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 ""
@ -1741,8 +1702,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 ""

@ -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,13 +178,13 @@ 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 ""
@ -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: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 #, 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,6 +547,7 @@ 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:19 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
@ -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,7 +615,7 @@ 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 ""
@ -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,11 +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:85
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
@ -873,7 +861,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 +888,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 +903,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 ""
@ -1058,7 +1046,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 +1056,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,27 +1116,18 @@ 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
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
msgid "Indexed?"
msgstr ""
#, elixir-format
#: 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 ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
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 ""
@ -1166,12 +1139,14 @@ 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"
@ -1186,22 +1161,14 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value" msgid "Error rendering value"
msgstr "" msgstr ""
""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
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
@ -1273,7 +1240,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 ""
@ -1479,8 +1446,8 @@ 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 ""
@ -1706,7 +1673,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 ""
@ -1741,8 +1708,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 ""

@ -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

@ -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

@ -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(
@ -2209,14 +2220,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 +2251,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 +2279,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 +2509,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 +3275,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 +3297,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

@ -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

@ -630,7 +630,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 +639,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 +657,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 +683,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 +693,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 +702,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 +2090,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 +2117,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 +2151,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 +2161,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 +2183,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 +2202,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 +2222,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 +2243,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 +2271,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 +2301,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 +2321,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 +2332,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 +2349,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 +2364,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 +2376,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 +2384,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 +2397,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 +2410,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 +2422,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 +2480,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 +2533,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

Loading…
Cancel
Save