Merge branch 'master' into ab-remove-temporary-modules

pull/1892/head
Ayrat Badykov 6 years ago committed by GitHub
commit 5c9414766a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      CHANGELOG.md
  2. 3
      README.md
  3. 1
      apps/block_scout_web/assets/css/components/_tooltip.scss
  4. 53
      apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
  5. 2
      apps/block_scout_web/assets/css/theme/_lukso_variables.scss
  6. 55
      apps/block_scout_web/assets/css/theme/_poa_variables.scss
  7. 50
      apps/block_scout_web/assets/css/theme/_rsk_variables.scss
  8. 41
      apps/block_scout_web/assets/static/images/ethereum_logo.svg
  9. 4
      apps/block_scout_web/assets/static/images/poa_logo.svg
  10. 47
      apps/block_scout_web/assets/static/images/rsk_logo.svg
  11. 17
      apps/block_scout_web/lib/block_scout_web/chain.ex
  12. 57
      apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
  13. 29
      apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
  14. 5
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  15. 212
      apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex
  16. 44
      apps/block_scout_web/priv/gettext/default.pot
  17. 44
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  18. 4
      apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs
  19. 1
      apps/explorer/.gitignore
  20. 1
      apps/explorer/lib/explorer/application.ex
  21. 22
      apps/explorer/lib/explorer/chain.ex
  22. 92
      apps/explorer/lib/explorer/smart_contract/solc_downloader.ex
  23. 9
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  24. 16
      apps/explorer/priv/compile_solc.js
  25. 27
      apps/explorer/test/explorer/chain_test.exs

@ -1,7 +1,11 @@
## Current ## Current
### Features ### Features
- [#1907](https://github.com/poanetwork/blockscout/pull/1907) - dropdown color bug fix (lukso theme) and tooltip color bug fix
- [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo
- [#1895](https://github.com/poanetwork/blockscout/pull/1895) - add changes to poa theme and poa logo
- [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page
- [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo
- [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x"
- [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page - [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page
- [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request
@ -18,6 +22,9 @@
- [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth - [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth
- [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance - [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance
- [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view - [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view
- [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code
- [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete
- [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance
### Chore ### Chore

@ -65,6 +65,7 @@ Currently available block explorers (i.e. Etherscan and Etherchain) are closed s
* [SpringChain](https://explorer.springrole.com/) * [SpringChain](https://explorer.springrole.com/)
* [PIRL](http://pirl.es/) * [PIRL](http://pirl.es/)
* [Petrichor](https://explorer.petrichor-dev.com/) * [Petrichor](https://explorer.petrichor-dev.com/)
* [Ether-1](https://blocks.ether1.wattpool.net/)
### Visual Interface ### Visual Interface
@ -139,7 +140,7 @@ The [development stack page](https://github.com/poanetwork/blockscout/wiki/Devel
``` ```
* If using Chrome, Enable `chrome://flags/#allow-insecure-localhost`. * If using Chrome, Enable `chrome://flags/#allow-insecure-localhost`.
9. Start Phoenix Server. 9. Run the Phoenix Server from the root directory of your application.
`mix phx.server` `mix phx.server`
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.

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

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

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

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

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

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

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

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

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 694 B

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

After

Width:  |  Height:  |  Size: 5.3 KiB

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

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

@ -1,12 +1,28 @@
<section class="container"> <section class="container">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<%= if @next_page_path do %>
<a href="<%= "#{@next_page_path}" %>" class="button button-secondary button-small float-right ml-1">
<%= gettext("Next") %>
</a>
<% end %>
<%= if @prev_page_path do %>
<a href="<%= "#{@prev_page_path}" %>" class="button button-secondary button-small float-right">
<%= gettext("Back") %>
</a>
<% end %>
<h1 class="card-title margin-bottom-0"><%= gettext "Addresses" %></h1> <h1 class="card-title margin-bottom-0"><%= gettext "Addresses" %></h1>
<p class="card-subtitle"> <p class="card-subtitle">
<%= gettext "Showing 250 addresses of" %> <%= gettext "Showing " %>
<%= Cldr.Number.to_string!(@page_address_count, format: "#,###") %>
<%= gettext " addresses of" %>
<%= Cldr.Number.to_string!(@address_count, format: "#,###") %> <%= Cldr.Number.to_string!(@address_count, format: "#,###") %>
<%= gettext "total addresses with a balance" %> <%= gettext "total addresses with a balance" %>
<%= gettext " (page" %>
<%= Cldr.Number.to_string!(@cur_page_number, format: "#,###)") %>
</p> </p>
<span data-selector="top-addresses-list"> <span data-selector="top-addresses-list">
<%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %> <%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %>
<%= render "_tile.html", <%= render "_tile.html",
@ -14,6 +30,17 @@
total_supply: @total_supply, tx_count: tx_count, total_supply: @total_supply, tx_count: tx_count,
validation_count: validation_count(address) %> validation_count: validation_count(address) %>
<% end %> <% end %>
<br>
<%= if @next_page_path do %>
<a href="<%= "#{@next_page_path}" %>" class="button button-secondary button-small float-right mt-0 mb-0 ml-1">
<%= gettext("Next") %>
</a>
<% end %>
<%= if @prev_page_path do %>
<a href="<%= "#{@prev_page_path}" %>" class="button button-secondary button-small float-right mt-0 mb-0">
<%= gettext("Back") %>
</a>
<% end %>
</span> </span>
</div> </div>
</div> </div>

@ -112,9 +112,8 @@
"data-test": "search_input" "data-test": "search_input"
], ],
[ url: "#{chain_path(@conn, :token_autocomplete)}?q=", [ url: "#{chain_path(@conn, :token_autocomplete)}?q=",
prepop: true, limit: 0,
minChars: 3, minChars: 2,
maxItems: 8,
value: "contract_address_hash", value: "contract_address_hash",
label: "contract_address_hash", label: "contract_address_hash",
descrSearch: true, descrSearch: true,

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

@ -104,7 +104,7 @@ msgid "Address"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:4 #: lib/block_scout_web/templates/address/index.html.eex:15
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59
msgid "Addresses" msgid "Addresses"
msgstr "" msgstr ""
@ -578,6 +578,8 @@ msgid "Newer"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
#: lib/block_scout_web/templates/address/index.html.eex:36
#: lib/block_scout_web/templates/address_token/index.html.eex:22 #: lib/block_scout_web/templates/address_token/index.html.eex:22
msgid "Next" msgid "Next"
msgstr "" msgstr ""
@ -712,7 +714,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111 #: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129 #: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -739,11 +741,6 @@ msgstr ""
msgid "Showing" msgid "Showing"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
msgid "Showing 250 addresses of"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8 #: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:210 #: lib/block_scout_web/views/transaction_view.ex:210
@ -1078,7 +1075,7 @@ msgid "string"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:8 #: lib/block_scout_web/templates/address/index.html.eex:21
msgid "total addresses with a balance" msgid "total addresses with a balance"
msgstr "" msgstr ""
@ -1708,11 +1705,6 @@ msgstr ""
msgid "ERC-721" msgid "ERC-721"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/index.html.eex:4 #: lib/block_scout_web/templates/api_docs/index.html.eex:4
msgid "API Documentation" msgid "API Documentation"
@ -1739,3 +1731,29 @@ msgstr ""
#: lib/block_scout_web/views/transaction_view.ex:341 #: lib/block_scout_web/views/transaction_view.ex:341
msgid "Raw Trace" msgid "Raw Trace"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:22
msgid " (page"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:19
msgid " addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:11
#: lib/block_scout_web/templates/address/index.html.eex:41
msgid "Back"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:17
msgid "Showing "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""

@ -104,7 +104,7 @@ msgid "Address"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:4 #: lib/block_scout_web/templates/address/index.html.eex:15
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59
msgid "Addresses" msgid "Addresses"
msgstr "" msgstr ""
@ -578,6 +578,8 @@ msgid "Newer"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
#: lib/block_scout_web/templates/address/index.html.eex:36
#: lib/block_scout_web/templates/address_token/index.html.eex:22 #: lib/block_scout_web/templates/address_token/index.html.eex:22
msgid "Next" msgid "Next"
msgstr "" msgstr ""
@ -712,7 +714,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111 #: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129 #: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -739,11 +741,6 @@ msgstr ""
msgid "Showing" msgid "Showing"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
msgid "Showing 250 addresses of"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8 #: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:210 #: lib/block_scout_web/views/transaction_view.ex:210
@ -1078,7 +1075,7 @@ msgid "string"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:8 #: lib/block_scout_web/templates/address/index.html.eex:21
msgid "total addresses with a balance" msgid "total addresses with a balance"
msgstr "" msgstr ""
@ -1708,11 +1705,6 @@ msgstr ""
msgid "ERC-721" msgid "ERC-721"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/index.html.eex:4 #: lib/block_scout_web/templates/api_docs/index.html.eex:4
msgid "API Documentation" msgid "API Documentation"
@ -1739,3 +1731,29 @@ msgstr ""
#: lib/block_scout_web/views/transaction_view.ex:341 #: lib/block_scout_web/views/transaction_view.ex:341
msgid "Raw Trace" msgid "Raw Trace"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:22
msgid " (page"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:19
msgid " addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:11
#: lib/block_scout_web/templates/address/index.html.eex:41
msgid "Back"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:17
msgid "Showing "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""

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

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

@ -26,6 +26,7 @@ defmodule Explorer.Application do
Supervisor.Spec.worker(SpandexDatadog.ApiServer, [datadog_opts()]), Supervisor.Spec.worker(SpandexDatadog.ApiServer, [datadog_opts()]),
Supervisor.child_spec({Task.Supervisor, name: Explorer.MarketTaskSupervisor}, id: Explorer.MarketTaskSupervisor), Supervisor.child_spec({Task.Supervisor, name: Explorer.MarketTaskSupervisor}, id: Explorer.MarketTaskSupervisor),
Supervisor.child_spec({Task.Supervisor, name: Explorer.TaskSupervisor}, id: Explorer.TaskSupervisor), Supervisor.child_spec({Task.Supervisor, name: Explorer.TaskSupervisor}, id: Explorer.TaskSupervisor),
Explorer.SmartContract.SolcDownloader,
{Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents}, {Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents},
{Admin.Recovery, [[], [name: Admin.Recovery]]}, {Admin.Recovery, [[], [name: Admin.Recovery]]},
{TransactionCountCache, [[], []]} {TransactionCountCache, [[], []]}

@ -1143,21 +1143,25 @@ defmodule Explorer.Chain do
end end
@doc """ @doc """
Lists the top 250 `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance. Lists the top `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance and address hash.
""" """
@spec list_top_addresses :: [{Address.t(), non_neg_integer()}] @spec list_top_addresses :: [{Address.t(), non_neg_integer()}]
def list_top_addresses do def list_top_addresses(options \\ []) do
query = paging_options = Keyword.get(options, :paging_options, @default_paging_options)
base_query =
from(a in Address, from(a in Address,
where: a.fetched_coin_balance > ^0, where: a.fetched_coin_balance > ^0,
order_by: [desc: a.fetched_coin_balance, asc: a.hash], order_by: [desc: a.fetched_coin_balance, asc: a.hash],
preload: [:names], preload: [:names],
select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)}, select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)}
limit: 250
) )
Repo.all(query) base_query
|> page_addresses(paging_options)
|> limit(^paging_options.page_size)
|> Repo.all()
end end
@doc """ @doc """
@ -2293,6 +2297,12 @@ defmodule Explorer.Chain do
end) end)
end end
defp page_addresses(query, %PagingOptions{key: nil}), do: query
defp page_addresses(query, %PagingOptions{key: {coin_balance, hash}}) do
where(query, [address], address.fetched_coin_balance <= ^coin_balance and address.hash > ^hash)
end
defp page_blocks(query, %PagingOptions{key: nil}), do: query defp page_blocks(query, %PagingOptions{key: nil}), do: query
defp page_blocks(query, %PagingOptions{key: {block_number}}) do defp page_blocks(query, %PagingOptions{key: {block_number}}) do

@ -0,0 +1,92 @@
defmodule Explorer.SmartContract.SolcDownloader do
@moduledoc """
Checks to see if the requested solc compiler version exists, and if not it
downloads and stores the file.
"""
use GenServer
alias Explorer.SmartContract.Solidity.CompilerVersion
@latest_compiler_refetch_time :timer.minutes(30)
def ensure_exists(version) do
path = file_path(version)
if File.exists?(path) do
path
else
{:ok, compiler_versions} = CompilerVersion.fetch_versions()
if version in compiler_versions do
GenServer.call(__MODULE__, {:ensure_exists, version}, 60_000)
else
false
end
end
end
def start_link(_) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
# sobelow_skip ["Traversal"]
@impl true
def init([]) do
File.mkdir(compiler_dir())
{:ok, []}
end
# sobelow_skip ["Traversal"]
@impl true
def handle_call({:ensure_exists, version}, _from, state) do
path = file_path(version)
if fetch?(version, path) do
temp_path = file_path("#{version}-tmp")
contents = download(version)
file = File.open!(temp_path, [:write, :exclusive])
IO.binwrite(file, contents)
File.rename(temp_path, path)
end
{:reply, path, state}
end
defp fetch?("latest", path) do
case File.stat(path) do
{:error, :enoent} ->
true
{:ok, %{mtime: mtime}} ->
last_modified = NaiveDateTime.from_erl!(mtime)
diff = Timex.diff(NaiveDateTime.utc_now(), last_modified, :milliseconds)
diff > @latest_compiler_refetch_time
end
end
defp fetch?(_, path) do
not File.exists?(path)
end
defp file_path(version) do
Path.join(compiler_dir(), "#{version}.js")
end
defp compiler_dir do
Application.app_dir(:explorer, "priv/solc_compilers/")
end
defp download(version) do
download_path = "https://ethereum.github.io/solc-bin/bin/soljson-#{version}.js"
download_path
|> HTTPoison.get!([], timeout: 60_000)
|> Map.get(:body)
end
end

@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
Module responsible to compile the Solidity code of a given Smart Contract. Module responsible to compile the Solidity code of a given Smart Contract.
""" """
alias Explorer.SmartContract.SolcDownloader
@new_contract_name "New.sol" @new_contract_name "New.sol"
@allowed_evm_versions ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"] @allowed_evm_versions ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"]
@ -79,6 +81,9 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
"byzantium" "byzantium"
end end
path = SolcDownloader.ensure_exists(compiler_version)
if path do
{response, _status} = {response, _status} =
System.cmd( System.cmd(
"node", "node",
@ -90,7 +95,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
optimization_runs, optimization_runs,
@new_contract_name, @new_contract_name,
external_libs_string, external_libs_string,
checked_evm_version checked_evm_version,
path
] ]
) )
@ -106,6 +112,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
parse_error(error) parse_error(error)
end end
end end
end
def allowed_evm_versions, do: @allowed_evm_versions def allowed_evm_versions, do: @allowed_evm_versions

@ -1,7 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
const solc = require('solc');
var sourceCode = process.argv[2]; var sourceCode = process.argv[2];
var version = process.argv[3]; var version = process.argv[3];
var optimize = process.argv[4]; var optimize = process.argv[4];
@ -9,11 +7,12 @@ var optimizationRuns = parseInt(process.argv[5], 10);
var newContractName = process.argv[6]; var newContractName = process.argv[6];
var externalLibraries = JSON.parse(process.argv[7]) var externalLibraries = JSON.parse(process.argv[7])
var evmVersion = process.argv[8]; var evmVersion = process.argv[8];
var compilerVersionPath = process.argv[9];
var solc = require('solc')
var compilerSnapshot = require(compilerVersionPath);
var solc = solc.setupMethods(compilerSnapshot);
var compiled_code = solc.loadRemoteVersion(version, function (err, solcSnapshot) {
if (err) {
console.log(JSON.stringify(err.message));
} else {
const input = { const input = {
language: 'Solidity', language: 'Solidity',
sources: { sources: {
@ -38,9 +37,8 @@ var compiled_code = solc.loadRemoteVersion(version, function (err, solcSnapshot)
} }
} }
const output = JSON.parse(solcSnapshot.compile(JSON.stringify(input)))
const output = JSON.parse(solc.compile(JSON.stringify(input)))
/** Older solc-bin versions don't use filename as contract key */ /** Older solc-bin versions don't use filename as contract key */
const response = output.contracts[newContractName] || output.contracts[''] const response = output.contracts[newContractName] || output.contracts['']
console.log(JSON.stringify(response)); console.log(JSON.stringify(response));
}
});

@ -1415,6 +1415,33 @@ defmodule Explorer.ChainTest do
|> Enum.map(fn {address, _transaction_count} -> address end) |> Enum.map(fn {address, _transaction_count} -> address end)
|> Enum.map(& &1.hash) |> Enum.map(& &1.hash)
end end
test "paginates addresses" do
test_hashes =
4..0
|> Enum.map(&Explorer.Chain.Hash.cast(Explorer.Chain.Hash.Address, &1))
|> Enum.map(&elem(&1, 1))
result =
4..1
|> Enum.map(&insert(:address, fetched_coin_balance: &1, hash: Enum.fetch!(test_hashes, &1 - 1)))
|> Enum.map(& &1.hash)
options = [paging_options: %PagingOptions{page_size: 1}]
[{top_address, _}] = Chain.list_top_addresses(options)
assert top_address.hash == List.first(result)
tail_options = [
paging_options: %PagingOptions{key: {top_address.fetched_coin_balance.value, top_address.hash}, page_size: 3}
]
tail_result = tail_options |> Chain.list_top_addresses() |> Enum.map(fn {address, _} -> address.hash end)
[_ | expected_tail] = result
assert tail_result == expected_tail
end
end end
describe "stream_blocks_without_rewards/2" do describe "stream_blocks_without_rewards/2" do

Loading…
Cancel
Save