diff --git a/.circleci/config.yml b/.circleci/config.yml
index f410162b48..b3abd48786 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,7 +3,7 @@ jobs:
build:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0-node-browsers
+ - image: circleci/elixir:1.9.1-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
@@ -129,7 +129,7 @@ jobs:
check_formatted:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: test
@@ -143,7 +143,7 @@ jobs:
credo:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: test
@@ -177,7 +177,7 @@ jobs:
dialyzer:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: test
@@ -247,7 +247,7 @@ jobs:
gettext:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: test
@@ -286,7 +286,7 @@ jobs:
release:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: prod
@@ -312,7 +312,7 @@ jobs:
sobelow:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: test
@@ -336,7 +336,7 @@ jobs:
test_geth_http_websocket:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0-node-browsers
+ - image: circleci/elixir:1.9.1-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
@@ -390,7 +390,7 @@ jobs:
test_geth_mox:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0-node-browsers
+ - image: circleci/elixir:1.9.1-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
@@ -444,7 +444,7 @@ jobs:
test_parity_http_websocket:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0-node-browsers
+ - image: circleci/elixir:1.9.1-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
@@ -498,7 +498,7 @@ jobs:
test_parity_mox:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0-node-browsers
+ - image: circleci/elixir:1.9.1-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
@@ -552,7 +552,7 @@ jobs:
coveralls_merge:
docker:
# Ensure .tool-versions matches
- - image: circleci/elixir:1.9.0
+ - image: circleci/elixir:1.9.1
environment:
MIX_ENV: test
diff --git a/.credo.exs b/.credo.exs
index ab3359abb1..ba4d7feb49 100644
--- a/.credo.exs
+++ b/.credo.exs
@@ -89,7 +89,7 @@
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`.
#
- {Credo.Check.Design.DuplicatedCode, excluded_macros: []},
+ {Credo.Check.Design.DuplicatedCode, excluded_macros: [], mass_threshold: 80},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
diff --git a/.tool-versions b/.tool-versions
index 71379b2fa7..785ba751f8 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1,3 +1,3 @@
-elixir 1.9
-erlang 21.0.4
+elixir 1.9.1-otp-22
+erlang 22.0
nodejs 10.11.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 75a5e56e6d..17adfb0acc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,13 +1,67 @@
## Current
### Features
+- [#2477](https://github.com/poanetwork/blockscout/pull/2477) - aggregate token transfers on transaction page
+- [#2458](https://github.com/poanetwork/blockscout/pull/2458) - Add LAST_BLOCK var to add ability indexing in the range of blocks
+- [#2456](https://github.com/poanetwork/blockscout/pull/2456) - fetch pending transactions for geth
- [#2403](https://github.com/poanetwork/blockscout/pull/2403) - Return gasPrice field at the result of gettxinfo method
+
+### Fixes
+- [#2520](https://github.com/poanetwork/blockscout/pull/2520) - Hide loading message when fetching is failed
+- [#2523](https://github.com/poanetwork/blockscout/pull/2523) - Avoid importing internal_transactions of pending transactions
+- [#2519](https://github.com/poanetwork/blockscout/pull/2519) - enable `First` page button in pagination
+- [#2515](https://github.com/poanetwork/blockscout/pull/2515) - do not aggregate NFT token transfers
+- [#2512](https://github.com/poanetwork/blockscout/pull/2512) - alert link fix
+- [#2508](https://github.com/poanetwork/blockscout/pull/2508) - logs view columns fix
+- [#2506](https://github.com/poanetwork/blockscout/pull/2506) - fix two active tab in the top menu
+- [#2503](https://github.com/poanetwork/blockscout/pull/2503) - Mitigate autocompletion library influence to page loading performance
+- [#2502](https://github.com/poanetwork/blockscout/pull/2502) - increase reward task timeout
+- [#2463](https://github.com/poanetwork/blockscout/pull/2463) - dark theme fixes
+- [#2496](https://github.com/poanetwork/blockscout/pull/2496) - fix docker build
+- [#2495](https://github.com/poanetwork/blockscout/pull/2495) - fix logs for indexed chain
+- [#2459](https://github.com/poanetwork/blockscout/pull/2459) - fix top addresses query
+- [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB
+
+### Chore
+- [#2507](https://github.com/poanetwork/blockscout/pull/2507) - update minor version of ecto, ex_machina, phoenix_live_reload
+- [#2516](https://github.com/poanetwork/blockscout/pull/2516) - update absinthe plug from fork
+- [#2473](https://github.com/poanetwork/blockscout/pull/2473) - get rid of cldr warnings
+- [#2402](https://github.com/poanetwork/blockscout/pull/2402) - bump otp version to 22.0
+- [#2492](https://github.com/poanetwork/blockscout/pull/2492) - hide decoded row if event is not decoded
+- [#2490](https://github.com/poanetwork/blockscout/pull/2490) - enable credo duplicated code check
+- [#2432](https://github.com/poanetwork/blockscout/pull/2432) - bump credo version
+- [#2457](https://github.com/poanetwork/blockscout/pull/2457) - update mix.lock
+- [#2435](https://github.com/poanetwork/blockscout/pull/2435) - Replace deprecated extract-text-webpack-plugin with mini-css-extract-plugin
+- [#2450](https://github.com/poanetwork/blockscout/pull/2450) - Fix clearance of logs and node_modules folders in clearing script
+- [#2434](https://github.com/poanetwork/blockscout/pull/2434) - get rid of timex warnings
+- [#2402](https://github.com/poanetwork/blockscout/pull/2402) - bump otp version to 22.0
+- [#2373](https://github.com/poanetwork/blockscout/pull/2373) - Add script to validate internal_transactions constraint for large DBs
+
+## 2.0.2-beta
+
+### Features
+- [#2412](https://github.com/poanetwork/blockscout/pull/2412) - dark theme
+- [#2399](https://github.com/poanetwork/blockscout/pull/2399) - decode verified smart contract's logs
+- [#2391](https://github.com/poanetwork/blockscout/pull/2391) - Controllers Improvements
- [#2379](https://github.com/poanetwork/blockscout/pull/2379) - Disable network selector when is empty
+- [#2374](https://github.com/poanetwork/blockscout/pull/2374) - decode constructor arguments for verified smart contracts
+- [#2366](https://github.com/poanetwork/blockscout/pull/2366) - paginate eth logs
- [#2360](https://github.com/poanetwork/blockscout/pull/2360) - add default evm version to smart contract verification
- [#2352](https://github.com/poanetwork/blockscout/pull/2352) - Fetch rewards in parallel with transactions
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
+- [#2324](https://github.com/poanetwork/blockscout/pull/2324) - set timeout for loading message on the main page
### Fixes
+- [#2421](https://github.com/poanetwork/blockscout/pull/2421) - Fix hiding of loader for txs on the main page
+- [#2420](https://github.com/poanetwork/blockscout/pull/2420) - fetch data from cache in healthy endpoint
+- [#2416](https://github.com/poanetwork/blockscout/pull/2416) - Fix "page not found" handling in the router
+- [#2413](https://github.com/poanetwork/blockscout/pull/2413) - remove outer tables for decoded data
+- [#2410](https://github.com/poanetwork/blockscout/pull/2410) - preload smart contract for logs decoding
+- [#2405](https://github.com/poanetwork/blockscout/pull/2405) - added templates for table loader and tile loader
+- [#2398](https://github.com/poanetwork/blockscout/pull/2398) - show only one decoded candidate
+- [#2389](https://github.com/poanetwork/blockscout/pull/2389) - Reduce Lodash lib size (86% of lib methods are not used)
+- [#2388](https://github.com/poanetwork/blockscout/pull/2388) - add create2 support to geth's js tracer
+- [#2387](https://github.com/poanetwork/blockscout/pull/2387) - fix not existing keys in transaction json rpc
- [#2378](https://github.com/poanetwork/blockscout/pull/2378) - Page performance: exclude moment.js localization files except EN, remove unused css
- [#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
@@ -25,6 +79,9 @@
- [#2326](https://github.com/poanetwork/blockscout/pull/2326) - fix nested constructor arguments
### Chore
+- [#2422](https://github.com/poanetwork/blockscout/pull/2422) - check if address_id is binary in token_transfers_csv endpoint
+- [#2418](https://github.com/poanetwork/blockscout/pull/2418) - Remove parentheses in market cap percentage
+- [#2401](https://github.com/poanetwork/blockscout/pull/2401) - add ENV vars to manage updating period of average block time and market history cache
- [#2363](https://github.com/poanetwork/blockscout/pull/2363) - add parameters example for eth rpc
- [#2342](https://github.com/poanetwork/blockscout/pull/2342) - Upgrade Postgres image version in Docker setup
- [#2325](https://github.com/poanetwork/blockscout/pull/2325) - Reduce function input to address' hash only where possible
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
index 3ac2a5a1d1..4f889b7304 100644
--- a/PULL_REQUEST_TEMPLATE.md
+++ b/PULL_REQUEST_TEMPLATE.md
@@ -35,3 +35,5 @@
- [ ] If I added new functionality, I added tests covering it.
- [ ] If I fixed a bug, I added a regression test to prevent the bug from silently reappearing again.
- [ ] I checked whether I should update the docs and did so if necessary
+ - [ ] If I added/changed/removed ENV var, I should update the list of env vars in https://github.com/poanetwork/blockscout/blob/master/docs/env-variables.md to reflect changes in the table here https://poanetwork.github.io/blockscout/#/env-variables?id=blockscout-env-variables. I've set `master` in the `Version` column.
+ - [ ] If I add new indices into DB, I checked, that they don't redundant with PGHero or other tools
diff --git a/apps/block_scout_web/assets/__tests__/lib/async_listing_load.js b/apps/block_scout_web/assets/__tests__/lib/async_listing_load.js
index 6e86d8a6b5..adae2d6033 100644
--- a/apps/block_scout_web/assets/__tests__/lib/async_listing_load.js
+++ b/apps/block_scout_web/assets/__tests__/lib/async_listing_load.js
@@ -46,14 +46,12 @@ describe('REQUEST_ERROR', () => {
describe('FINISH_REQUEST', () => {
test('sets loading status to false', () => {
const state = Object.assign({}, asyncInitialState, {
- loading: true,
- loadingFirstPage: true
+ loading: true
})
const action = { type: 'FINISH_REQUEST' }
const output = asyncReducer(state, action)
expect(output.loading).toEqual(false)
- expect(output.loadingFirstPage).toEqual(false)
})
})
diff --git a/apps/block_scout_web/assets/__tests__/pages/pending_transactions.js b/apps/block_scout_web/assets/__tests__/pages/pending_transactions.js
index e9f7fc941d..ddbf84ce7d 100644
--- a/apps/block_scout_web/assets/__tests__/pages/pending_transactions.js
+++ b/apps/block_scout_web/assets/__tests__/pages/pending_transactions.js
@@ -1,4 +1,3 @@
-import _ from 'lodash'
import { reducer, initialState } from '../../js/pages/pending_transactions'
test('CHANNEL_DISCONNECTED', () => {
diff --git a/apps/block_scout_web/assets/css/app.scss b/apps/block_scout_web/assets/css/app.scss
index cf79ee46e8..e91df91740 100644
--- a/apps/block_scout_web/assets/css/app.scss
+++ b/apps/block_scout_web/assets/css/app.scss
@@ -128,6 +128,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/new_smart_contract";
@import "components/radio_big";
@import "components/btn_no_border";
+@import "theme/dark-theme";
:export {
dashboardBannerChartAxisFontColor: $dashboard-banner-chart-axis-font-color;
@@ -135,4 +136,6 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
dashboardLineColorPrice: $dashboard-line-color-price;
primary: $primary;
secondary: $secondary;
+ darkprimary: $dark-primary;
+ darksecondary: $dark-secondary;
}
diff --git a/apps/block_scout_web/assets/css/components/_navbar.scss b/apps/block_scout_web/assets/css/components/_navbar.scss
index 48c6c50f02..0d892b25ca 100644
--- a/apps/block_scout_web/assets/css/components/_navbar.scss
+++ b/apps/block_scout_web/assets/css/components/_navbar.scss
@@ -252,4 +252,10 @@ $navbar-logo-width: auto !default;
@include media-breakpoint-up(xl) {
padding-right: 0;
}
+}
+
+.nav-item-networks {
+ .topnav-nav-link {
+ transition: none !important;
+ }
}
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/components/_stakes_table.scss b/apps/block_scout_web/assets/css/components/_stakes_table.scss
index 79cdc20b38..1831dc4d5b 100644
--- a/apps/block_scout_web/assets/css/components/_stakes_table.scss
+++ b/apps/block_scout_web/assets/css/components/_stakes_table.scss
@@ -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 {
min-width: fit-content;
width: 100%;
diff --git a/apps/block_scout_web/assets/css/components/_tile.scss b/apps/block_scout_web/assets/css/components/_tile.scss
index 8965715727..e621e4fd6d 100644
--- a/apps/block_scout_web/assets/css/components/_tile.scss
+++ b/apps/block_scout_web/assets/css/components/_tile.scss
@@ -339,9 +339,9 @@ $tile-body-a-color: #5959d8 !default;
padding-left: 6px;
padding-right: 6px;
}
- .tile-type-block {
- overflow: hidden;
- }
+ }
+ .tile-type-block {
+ overflow: hidden;
}
.row {
@include media-breakpoint-down(lg) {
@@ -351,3 +351,214 @@ $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
+
+@keyframes playBlockLoadingAnimation {
+ 0%, 90% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
+
+[data-selector="chain-block-list"] {
+ .col-lg-3:first-child {
+ .tile-type-block-animation {
+ animation: playBlockLoadingAnimation 2.1s linear forwards;
+ }
+ }
+}
+
+.fade-up-blocks-chain {
+ .tile-type-block {
+ position: relative;
+ }
+ .tile-type-block-animation {
+ opacity: 0;
+ position: absolute;
+ top: -1px;
+ left: -4px;
+ width: calc(100% + 5px);
+ height: calc(100% + 2px);
+ background-color: #F6F7F9;
+ border-radius: 4px;
+ overflow: hidden;
+ transition: .24s ease-out;
+ border-top: 1px solid #dee2e6;
+ border-right: 1px solid #dee2e6;
+ border-bottom: 1px solid #dee2e6;
+ pointer-events: none;
+ .tile-type-line-up {
+ position: absolute;
+ bottom: -1px;
+ left: 0;
+ height: calc(100% + 2px);
+ width: 4px;
+ background-color: $tile-type-block-color;
+ transform: scaleY(0);
+ transform-origin: center bottom;
+ animation: blockLoaderLine 2s linear forwards;
+ z-index: 2;
+ }
+ &:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 1px;
+ background-color: #dee2e6;
+ }
+ }
+}
+
+.cube-animation-title {
+ font-size: 12px;
+ color: #a3a9b5;
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ transform: translateX(-50%);
+}
+
+.fade-up-blocks-chain:first-child {
+ .tile-type-block-animation {
+ opacity: 1;
+ }
+}
+
+@keyframes blockLoaderLine {
+ 0% {
+ transform: scaleY(0);
+ }
+ 100% {
+ transform: scaleY(1);
+ }
+}
+
+$cube-bezier: cubic-bezier(.25,.8,.25,1);
+$cube-quantity: 5;
+
+.cube-animation-wrapper {
+ width: 560px;
+ height: 290px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%) scale(0.26);
+ svg {
+ width: 50px;
+ margin-top: -29px;
+
+ .side {
+ fill: $tile-type-block-color;
+ opacity: 1;
+
+ &:nth-of-type(2) {
+ fill: lighten($tile-type-block-color, 30);
+ opacity: 0.5;
+ }
+
+ &:nth-of-type(3) {
+ fill: lighten($tile-type-block-color, 80);
+ opacity: 0.5;
+ }
+ }
+ }
+
+ @while $cube-quantity > 0 {
+ .cube-animation-row:nth-of-type(#{$cube-quantity}) {
+ left: 25px * $cube-quantity;
+ top: 15px * $cube-quantity;
+ }
+ .cube-animation-column:nth-of-type(#{$cube-quantity}) {
+ position: relative;
+ top: 14px * $cube-quantity;
+ left: 25px * $cube-quantity;
+ }
+ .cube-animation-column:nth-of-type(#{$cube-quantity}) svg {
+ transform: translate3d(0,0,0);
+ animation: shrink-expand 2.8s $cube-bezier forwards;
+ animation-delay: -0.16s * $cube-quantity;
+ }
+
+ $cube-quantity: $cube-quantity - 1;
+ }
+}
+
+.cube-animation-center {
+ position: absolute;
+ top: 6%;
+ left: 20%;
+}
+
+.cube-animation-row {
+ display: flex;
+ flex-direction: row-reverse;
+ position: absolute;
+}
+
+.cube-animation-column {
+ display: flex;
+ flex-direction: column-reverse;
+}
+
+@keyframes shrink-expand {
+ 0% {
+ transform: scale(0);
+ }
+ 50% {
+ transform: scale(1);
+ }
+ 100% {
+ transform: scale(0);
+ }
+}
diff --git a/apps/block_scout_web/assets/css/theme/_base_variables.scss b/apps/block_scout_web/assets/css/theme/_base_variables.scss
index 9f1b82c887..2238327bd4 100644
--- a/apps/block_scout_web/assets/css/theme/_base_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_base_variables.scss
@@ -70,7 +70,10 @@ $colors: map-merge(
);
$primary: $indigo !default;
+$dark-primary: #9b62ff !default;
+$dark-primary-alternate: #9b62ff !default;
$secondary: #7dd79f !default;
+$dark-secondary: #87e1a9 !default;
$tertiary: $purple !default;
$success: $green !default;
$info: $cyan !default;
diff --git a/apps/block_scout_web/assets/css/theme/_dai_variables.scss b/apps/block_scout_web/assets/css/theme/_dai_variables.scss
index 50cbcfa290..0c09660240 100644
--- a/apps/block_scout_web/assets/css/theme/_dai_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_dai_variables.scss
@@ -62,4 +62,9 @@ $card-tab-active: $secondary;
// Badges
$badge-neutral-color: #20446e;
$badge-neutral-background-color: rgba(#20446e, .1);
-$api-text-monospace-color: #20446e;
\ No newline at end of file
+$api-text-monospace-color: #20446e;
+
+// Dark theme
+$dark-primary: #15bba6;
+$dark-secondary: #93d7ff;
+$dark-primary-alternate: #15bba6;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_dark-theme.scss b/apps/block_scout_web/assets/css/theme/_dark-theme.scss
new file mode 100644
index 0000000000..fe807aea60
--- /dev/null
+++ b/apps/block_scout_web/assets/css/theme/_dark-theme.scss
@@ -0,0 +1,688 @@
+$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 !important;
+ }
+
+ // Contract Verification
+ .new-smart-contract-container {
+ background-color: $dark-light-bg;
+ background-image: linear-gradient(to bottom right, $dark-light 100%, $dark-light 100%);
+ @media (max-width: 991.98px) {
+ background-image: none;
+ }
+ }
+ .smart-contract-form-group-inner-wrapper .smart-contract-form-group-tooltip {
+ color: $labels-dark;
+ }
+ .smart-contract-title {
+ color: #fff;
+ }
+ .smart-contract-form-group-inner-wrapper > label {
+ color: $labels-dark;
+ }
+ .smart-contract-form-buttons {
+ border-top-color: darken($labels-dark, 30);
+ .btn-no-border {
+ background-color: $dark-light;
+ border-color: $dark-light;
+ color: #fff;
+ &:hover {
+ background-color: $dark-primary;
+ color: #fff;
+ }
+ }
+ }
+ .add-contract-libraries-wrapper {
+ border-top-color: darken($labels-dark, 30);
+ }
+
+ .token-tile-view-more:before, .token-tile-view-more:after {
+ border-top-color: darken($labels-dark, 30);
+ border-bottom-color: darken($labels-dark, 30);
+ }
+
+ // Form Controlls
+ .form-control {
+ background-color: $dark-light;
+ border-color: $dark-light;
+ color: #fff;
+ &::placeholder {
+ color: $labels-dark;
+ }
+ &:focus {
+ background-color: $dark-light;
+ border-color: $dark-primary;
+ color: #fff;
+ }
+ }
+ .radio-big .radio-icon {
+ border-color: $labels-dark;
+ }
+ .radio-big input[type="radio"]:checked + .radio-icon {
+ border-color: $dark-primary;
+ }
+ .radio-big input[type="radio"]:checked + .radio-icon::before {
+ background: $dark-primary;
+ }
+ .radio-big .radio-text {
+ color: #fff;
+ }
+
+ // Content loading placeholders
+ .tile-loader, .table-content-loader {
+ background-color: $dark-bg !important;
+ &:before {
+ background: linear-gradient(to right, $dark-bg 2%, lighten($dark-bg, 3) 18%, $dark-bg 33%);
+ }
+ }
+
+ // Verify other explorers
+ .verify-other-explorers-elem {
+ border-color: darken($labels-dark, 30);
+ .exp-logo {
+ border-right-color: darken($labels-dark, 30);
+ }
+ .exp-content {
+ h3 {
+ color: #fff;
+ }
+ div {
+ color: $labels-dark;
+ }
+ }
+ }
+ .verify-other-explorers-more {
+ border-color: $dark-primary;
+ svg path {
+ fill: $dark-primary;
+ }
+ &:hover {
+ background-color: $dark-primary;
+ svg path {
+ fill: #fff;
+ }
+ }
+ }
+ .verify-other-explorers-elem {
+ &:hover {
+ text-decoration: none;
+ color: #fff;
+ .exp-content {
+ h3, div {
+ color: #fff;
+ }
+ }
+ }
+ }
+ .verify-other-explorers-cell {
+ .exp-logo {
+ color: #333 !important;
+ }
+ }
+
+ // API docs dropdown content
+ .api-doc-parameters-list-item-description,
+ .api-doc-parameters-list-item-title,
+ .api-doc-parameters-list-title,
+ .api-doc-list-item-controls-view-more {
+ color: #fff;
+ }
+
+ .api-doc-parameters-list {
+ border-bottom-color: darken($labels-dark, 30);
+ }
+ .api-doc-parameters-container {
+ border-top-color: darken($labels-dark, 30);
+ }
+ .api-doc-tab {
+ color: $dark-primary !important;
+ &.active {
+ border-bottom-color: $dark-primary;
+ }
+ }
+
+ // Common Buttons
+ .btn-secondary, .button-secondary {
+ background-color: transparent;
+ border-color: $dark-primary;
+ color: $dark-primary;
+ &:hover {
+ background-color: $dark-primary;
+ border-color: $dark-primary;
+ color: #fff;
+ }
+ }
+
+ .awesomplete {
+ & > ul {
+ background: $dark-light-bg;
+ &:before {
+ background: $dark-light-bg;
+ }
+ li {
+ &:hover {
+ background-color: $dark-primary;
+ color: #fff;
+ mark {
+ background: darken($dark-primary, 10);
+ color: #fff;
+ }
+ }
+ }
+ }
+ mark {
+ background: $dark-primary;
+ color: #fff;
+ }
+ }
+
+ // Decoded data
+ .table.thead-light.table-bordered {
+ color: #fff !important;
+ }
+ .table-bordered, .table-bordered td, .table-bordered th {
+ border-color: darken($labels-dark, 30);
+ }
+ .dark-theme-applied .table td, .dark-theme-applied .table th, .dark-theme-applied hr {
+ border-top-color: darken($labels-dark, 30);
+ }
+ .btn-copy-ico svg path {
+ fill: #fff;
+ }
+
+ // pre
+ .pre-scrollable.line-numbers, .hljs {
+ background: $dark-light;
+ color: #fff;
+ }
+
+ .hljs-comment {
+ color: $labels-dark;
+ }
+
+ .hljs-title, .hljs-section {
+ color: #ff2294;
+ }
+
+ .hljs-type, .hljs-string, .hljs-number, .hljs-selector-id, .hljs-selector-class, .hljs-quote, .hljs-template-tag, .hljs-deletion {
+ color: #ff2294;
+ }
+
+ .hljs-literal, .hljs-built_in, .hljs-bullet, .hljs-code, .hljs-addition {
+ color: #20dd94;
+ }
+
+ .line-numbers [data-line-number]:before {
+ color: #3f436b !important;
+ border-right-color: #3f436b !important;
+ }
+
+ // alert link
+ .alert-link {
+ color: $dark-secondary;
+ }
+}
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss b/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
index 68feab4dfc..dff677d7cc 100644
--- a/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
@@ -74,4 +74,9 @@ $card-tab-active: $tertiary;
// Badges
$badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1);
-$api-text-monospace-color: $tertiary;
\ No newline at end of file
+$api-text-monospace-color: $tertiary;
+
+// Dark theme
+$dark-primary: #8588ff;
+$dark-secondary: #4ad7a7;
+$dark-primary-alternate: #5b5ed8;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss b/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
index 0755d3e4b4..0b5cac0c43 100644
--- a/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
@@ -56,4 +56,18 @@ $card-tab-active: $secondary;
$dashboard-banner-gradient-end
);
}
+}
+
+// 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;
+ }
}
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_goerli_variables.scss b/apps/block_scout_web/assets/css/theme/_goerli_variables.scss
index 7900dd4c3b..04f953b477 100644
--- a/apps/block_scout_web/assets/css/theme/_goerli_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_goerli_variables.scss
@@ -78,3 +78,8 @@ $card-tab-active: $sub-accent-color;
$badge-neutral-color: $sub-accent-color;
$badge-neutral-background-color: rgba($sub-accent-color, .1);
$api-text-monospace-color: $sub-accent-color;
+
+// Dark theme
+$dark-primary: #e1995a;
+$dark-secondary: #aeaeae;
+$dark-primary-alternate: #e1995a;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_kovan_variables.scss b/apps/block_scout_web/assets/css/theme/_kovan_variables.scss
index 351f046726..a4edc629d0 100644
--- a/apps/block_scout_web/assets/css/theme/_kovan_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_kovan_variables.scss
@@ -74,4 +74,9 @@ $badge-success-color: #15bba6;
$badge-success-background-color: rgba(#15bba6, .1);
$badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1);
-$api-text-monospace-color: $tertiary;
\ No newline at end of file
+$api-text-monospace-color: $tertiary;
+
+// Dark theme
+$dark-primary: #42e2d7;
+$dark-secondary: #1f857f;
+$dark-primary-alternate: #1f857f;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_lukso_variables.scss b/apps/block_scout_web/assets/css/theme/_lukso_variables.scss
index 65f9a73b5f..a7b608bfa8 100644
--- a/apps/block_scout_web/assets/css/theme/_lukso_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_lukso_variables.scss
@@ -151,3 +151,20 @@ $dashboard-banner-network-plain-container-height: 150px;
$badge-neutral-color: $tertiary;
$badge-neutral-background-color: rgba($tertiary, .1);
$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;
+ }
+}
diff --git a/apps/block_scout_web/assets/css/theme/_neutral_variables.scss b/apps/block_scout_web/assets/css/theme/_neutral_variables.scss
index 4033934dd6..120a11c222 100644
--- a/apps/block_scout_web/assets/css/theme/_neutral_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_neutral_variables.scss
@@ -71,4 +71,9 @@ $api-text-monospace-color: $primary;
.dropdown-items .dropdown-item:hover {
color: $primary !important;
}
-}
\ No newline at end of file
+}
+
+// Dark theme
+$dark-primary: #9b62ff;
+$dark-secondary: #87e1a9;
+$dark-primary-alternate: #7e50d0;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_poa_variables.scss b/apps/block_scout_web/assets/css/theme/_poa_variables.scss
index 4033934dd6..120a11c222 100644
--- a/apps/block_scout_web/assets/css/theme/_poa_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_poa_variables.scss
@@ -71,4 +71,9 @@ $api-text-monospace-color: $primary;
.dropdown-items .dropdown-item:hover {
color: $primary !important;
}
-}
\ No newline at end of file
+}
+
+// Dark theme
+$dark-primary: #9b62ff;
+$dark-secondary: #87e1a9;
+$dark-primary-alternate: #7e50d0;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss b/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
index 1e62ea6d69..4fa700c50e 100644
--- a/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
@@ -57,3 +57,8 @@ $card-tab-active: $secondary;
);
}
}
+
+// Dark theme
+$dark-primary: #38a9f5;
+$dark-secondary: #76f1ff;
+$dark-primary-alternate: #38a9f5;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss b/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
index 1e62ea6d69..4fa700c50e 100644
--- a/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
@@ -57,3 +57,8 @@ $card-tab-active: $secondary;
);
}
}
+
+// Dark theme
+$dark-primary: #38a9f5;
+$dark-secondary: #76f1ff;
+$dark-primary-alternate: #38a9f5;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_rsk_variables.scss b/apps/block_scout_web/assets/css/theme/_rsk_variables.scss
index 76029e1a34..d33996a89e 100644
--- a/apps/block_scout_web/assets/css/theme/_rsk_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_rsk_variables.scss
@@ -65,3 +65,8 @@ $card-tab-active: $secondary;
// Badges
$badge-neutral-color: #1a323b;
$badge-neutral-background-color: rgba(#1a323b, .1);
+
+// Dark theme
+$dark-primary: #38c5a4;
+$dark-secondary: #e39a54;
+$dark-primary-alternate: #30ab8d;
diff --git a/apps/block_scout_web/assets/css/theme/_sokol_variables.scss b/apps/block_scout_web/assets/css/theme/_sokol_variables.scss
index 444cdff178..8d479f397d 100644
--- a/apps/block_scout_web/assets/css/theme/_sokol_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_sokol_variables.scss
@@ -72,4 +72,9 @@ $card-tab-active: $sub-accent-color;
// Badges
$badge-neutral-color: $tertiary;
-$badge-neutral-background-color: rgba($tertiary, .1);
\ No newline at end of file
+$badge-neutral-background-color: rgba($tertiary, .1);
+
+// Dark theme
+$dark-primary: #40bfb2;
+$dark-secondary: #25c9ff;
+$dark-primary-alternate: #1c9f90;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/js/app.js b/apps/block_scout_web/assets/js/app.js
index 25de7b2688..89059dd306 100644
--- a/apps/block_scout_web/assets/js/app.js
+++ b/apps/block_scout_web/assets/js/app.js
@@ -35,6 +35,7 @@ import './pages/favorites'
import './pages/network-search'
import './pages/layout'
import './pages/verification_form'
+import './pages/dark-mode-switcher'
import './pages/admin/tasks.js'
diff --git a/apps/block_scout_web/assets/js/lib/async_listing_load.js b/apps/block_scout_web/assets/js/lib/async_listing_load.js
index 8610d901f6..1c1fec4baa 100644
--- a/apps/block_scout_web/assets/js/lib/async_listing_load.js
+++ b/apps/block_scout_web/assets/js/lib/async_listing_load.js
@@ -1,5 +1,6 @@
import $ from 'jquery'
-import _ from 'lodash'
+import map from 'lodash/map'
+import merge from 'lodash/merge'
import URI from 'urijs'
import humps from 'humps'
import listMorph from '../lib/list_morph'
@@ -50,8 +51,6 @@ export const asyncInitialState = {
requestError: false,
/* if response has no items */
emptyResponse: false,
- /* if it is loading the first page */
- loadingFirstPage: true,
/* link to the next page */
nextPagePath: null,
/* link to the previous page */
@@ -79,8 +78,7 @@ export function asyncReducer (state = asyncInitialState, action) {
}
case 'FINISH_REQUEST': {
return Object.assign({}, state, {
- loading: false,
- loadingFirstPage: false
+ loading: false
})
}
case 'ITEMS_FETCHED': {
@@ -133,7 +131,7 @@ export const elements = {
},
'[data-async-listing] [data-loading-message]': {
render ($el, state) {
- if (state.loadingFirstPage) return $el.show()
+ if (state.loading) return $el.show()
$el.hide()
}
@@ -142,7 +140,7 @@ export const elements = {
render ($el, state) {
if (
!state.requestError &&
- (!state.loading || !state.loadingFirstPage) &&
+ (!state.loading) &&
state.items.length === 0
) {
return $el.show()
@@ -164,7 +162,7 @@ export const elements = {
if (state.itemKey) {
const container = $el[0]
- const newElements = _.map(state.items, (item) => $(item)[0])
+ const newElements = map(state.items, (item) => $(item)[0])
listMorph(container, newElements, { key: state.itemKey })
return
}
@@ -200,6 +198,16 @@ export const elements = {
$el.attr('href', state.prevPagePath)
}
},
+ '[data-async-listing] [data-first-page-button]': {
+ render ($el, state) {
+ if (state.pagesStack.length === 0) {
+ return $el.hide()
+ }
+ $el.show()
+ $el.attr('disabled', false)
+ $el.attr('href', window.location.href.split('?')[0])
+ }
+ },
'[data-async-listing] [data-page-number]': {
render ($el, state) {
if (state.emptyResponse) {
@@ -215,7 +223,7 @@ export const elements = {
},
'[data-async-listing] [data-loading-button]': {
render ($el, state) {
- if (!state.loadingFirstPage && state.loading) return $el.show()
+ if (state.loading) return $el.show()
$el.hide()
}
@@ -244,7 +252,7 @@ export const elements = {
* adding or removing with the correct animation. Check list_morph.js for more informantion.
*/
export function createAsyncLoadStore (reducer, initialState, itemKey) {
- const state = _.merge(asyncInitialState, initialState)
+ const state = merge(asyncInitialState, initialState)
const store = createStore(reduceReducers(asyncReducer, reducer, state))
if (typeof itemKey !== 'undefined') {
diff --git a/apps/block_scout_web/assets/js/lib/awesomplete-util.js b/apps/block_scout_web/assets/js/lib/awesomplete-util.js
new file mode 100644
index 0000000000..5b37e1dd2f
--- /dev/null
+++ b/apps/block_scout_web/assets/js/lib/awesomplete-util.js
@@ -0,0 +1,637 @@
+/* eslint-env browser */
+/* global Awesomplete */
+/* exported AwesompleteUtil */
+
+/*
+ * Library endorsing Lea Verou's Awesomplete widget, providing:
+ * - dynamic remote data loading
+ * - labels with HTML markup
+ * - events and styling for exact matches
+ * - events and styling for mismatches
+ * - select item when TAB key is used
+ *
+ * (c) Nico Hoogervorst
+ * License: MIT
+ *
+ */
+window.AwesompleteUtil = (function () {
+ //
+ // event names and css classes
+ //
+ var _AWE = 'awesomplete-'
+ var _AWE_LOAD = _AWE + 'loadcomplete'
+ var _AWE_CLOSE = _AWE + 'close'
+ var _AWE_MATCH = _AWE + 'match'
+ var _AWE_PREPOP = _AWE + 'prepop'
+ var _AWE_SELECT = _AWE + 'select'
+ var _CLS_FOUND = 'awe-found'
+ var _CLS_NOT_FOUND = 'awe-not-found'
+ var $ = Awesomplete.$ /* shortcut for document.querySelector */
+
+ //
+ // private functions
+ //
+
+ // Some parts are shamelessly copied from Awesomplete.js like the logic inside this _suggestion function.
+ // Returns an object with label and value properties. Data parameter is plain text or Object/Array with label and value.
+ function _suggestion (data) {
+ var lv = Array.isArray(data)
+ ? { label: data[0], value: data[1] }
+ : typeof data === 'object' && 'label' in data && 'value' in data ? data : { label: data, value: data }
+ return {label: lv.label || lv.value, value: lv.value}
+ }
+
+ // Helper to send events with detail property.
+ function _fire (target, name, detail) {
+ // $.fire uses deprecated methods but other methods don't work in IE11.
+ return $.fire(target, name, {detail: detail})
+ }
+
+ // Look if there is an exact match or a mismatch, set awe-found, awe-not-found css class and send match events.
+ function _matchValue (awe, prepop) {
+ var input = awe.input /* the input field */
+ var classList = input.classList
+ var utilprops = awe.utilprops /* extra properties piggybacked on Awesomplete object */
+ var selected = utilprops.selected /* the exact selected Suggestion with label and value */
+ var val = utilprops.convertInput.call(awe, input.value) /* trimmed lowercased value */
+ var opened = awe.opened /* is the suggestion list opened? */
+ var result = [] /* matches with value */
+ var list = awe._list /* current list of suggestions */
+ var suggestion, fake, rec, j /* function scoped variables */
+ utilprops.prepop = false /* after the first call it's not a prepopulation phase anymore */
+ if (list) { /* if there is a suggestion list */
+ for (j = 0; j < list.length; j++) { /* loop all suggestions */
+ rec = list[j]
+ suggestion = _suggestion(awe.data(rec, val)) /* call data convert function */
+ // with maxItems = 0 cannot look if suggestion list is opened to determine if there are still matches,
+ // instead call the filter method to see if there are still some options.
+ if (awe.maxItems === 0) {
+ // Awesomplete.FILTER_CONTAINS and Awesomplete.FILTER_STARTSWITH use the toString method.
+ suggestion.toString = function () { return '' + this.label }
+ if (awe.filter(suggestion, val)) {
+ // filter returns true, so there is at least one partial match.
+ opened = true
+ }
+ }
+ // Don't want to change the real input field, emulate a fake one.
+ fake = {input: {value: ''}}
+ // Determine how this suggestion would look like if it is replaced in the input field,
+ // it is an exact match if somebody types exactly that.
+ // Use the fake input here. fake.input.value will contain the result of the replace function.
+ awe.replace.call(fake, suggestion)
+ // Trim and lowercase also the fake input and compare that with the currently typed-in value.
+ if (utilprops.convertInput.call(awe, fake.input.value) === val) {
+ // This is an exact match. However there might more suggestions with the same value.
+ // If the user selected a suggestion from the list, check if this one matches, assuming that
+ // value + label is unique (if not it will be difficult for the user to make an informed decision).
+ if (selected && selected.value === suggestion.value && selected.label === suggestion.label) {
+ // this surely is the selected one
+ result = [rec]
+ break
+ }
+ // add the matching record to the result set.
+ result.push(rec)
+ } // end if
+ } // end loop
+
+ // if the result differs from the previous result
+ if (utilprops.prevSelected !== result) {
+ // if there is an exact match
+ if (result.length > 0) {
+ // if prepopulation phase (initial/autofill value); not triggered by user input
+ if (prepop) {
+ _fire(input, _AWE_PREPOP, result)
+ } else if (utilprops.changed) { /* if input is changed */
+ utilprops.prevSelected = result /* new result */
+ classList.remove(_CLS_NOT_FOUND) /* remove class */
+ classList.add(_CLS_FOUND) /* add css class */
+ _fire(input, _AWE_MATCH, result) /* fire event */
+ }
+ } else if (prepop) { /* no exact match, if in prepopulation phase */
+ _fire(input, _AWE_PREPOP, [])
+ } else if (utilprops.changed) { /* no exact match, if input is changed */
+ utilprops.prevSelected = []
+ classList.remove(_CLS_FOUND)
+ // Mark as not-found if there are no suggestions anymore or if another field is now active
+ if (!opened || (input !== document.activeElement)) {
+ if (val.length > 0) {
+ classList.add(_CLS_NOT_FOUND)
+ _fire(input, _AWE_MATCH, [])
+ }
+ } else {
+ classList.remove(_CLS_NOT_FOUND)
+ }
+ }
+ }
+ }
+ }
+
+ // Listen to certain events of THIS awesomplete object to trigger input validation.
+ function _match (ev) {
+ var awe = this
+ if ((ev.type === _AWE_CLOSE || ev.type === _AWE_LOAD || ev.type === 'blur') && ev.target === awe.input) {
+ _matchValue(awe, awe.utilprops.prepop && ev.type === _AWE_LOAD)
+ }
+ }
+
+ // Select currently selected item if tab or shift-tab key is used.
+ function _onKeydown (ev) {
+ var awe = this
+ if (ev.target === awe.input && ev.keyCode === 9) { // TAB key
+ awe.select() // take current selected item
+ }
+ }
+
+ // Handle selection event. State changes when an item is selected.
+ function _select (ev) {
+ var awe = this
+ awe.utilprops.changed = true // yes, user made a change
+ awe.utilprops.selected = ev.text // Suggestion object
+ }
+
+ // check if the object is empty {} object
+ function _isEmpty (val) {
+ return Object.keys(val).length === 0 && val.constructor === Object
+ }
+
+ // Need an updated suggestion list if:
+ // - There is no result yet, or there is a result but not for the characters we entered
+ // - or there might be more specific results because the limit was reached.
+ function _ifNeedListUpdate (awe, val, queryVal) {
+ var utilprops = awe.utilprops
+ return (!utilprops.listQuery ||
+ (!utilprops.loadall && /* with loadall, if there is a result, there is no need for new lists */
+ val.lastIndexOf(queryVal, 0) === 0 &&
+ (val.lastIndexOf(utilprops.listQuery, 0) !== 0 ||
+ (typeof utilprops.limit === 'number' && awe._list.length >= utilprops.limit))))
+ }
+
+ // Set a new suggestion list. Trigger loadcomplete event.
+ function _loadComplete (awe, list, queryVal) {
+ awe.list = list
+ awe.utilprops.listQuery = queryVal
+ _fire(awe.input, _AWE_LOAD, queryVal)
+ }
+
+ // Handle ajax response. Expects HTTP OK (200) response with JSON object with suggestion(s) (array).
+ function _onLoad () {
+ var t = this
+ var awe = t.awe
+ var xhr = t.xhr
+ var queryVal = t.queryVal
+ var val = awe.utilprops.val
+ var data
+ var prop
+ if (xhr.status === 200) {
+ data = JSON.parse(xhr.responseText)
+ if (awe.utilprops.convertResponse) data = awe.utilprops.convertResponse(data)
+ if (!Array.isArray(data)) {
+ if (awe.utilprops.limit === 0 || awe.utilprops.limit === 1) {
+ // if there is max 1 result expected, the array is not needed.
+ // Fur further processing, take the whole result and put it as one element in an array.
+ data = _isEmpty(data) ? [] : [data]
+ } else {
+ // search for the first property that contains an array
+ for (prop in data) {
+ if (Array.isArray(data[prop])) {
+ data = data[prop]
+ break
+ }
+ }
+ }
+ }
+ // can only handle arrays
+ if (Array.isArray(data)) {
+ // are we still interested in this response?
+ if (_ifNeedListUpdate(awe, val, queryVal)) {
+ // accept the new suggestion list
+ _loadComplete(awe, data, queryVal || awe.utilprops.loadall)
+ }
+ }
+ }
+ }
+
+ // Perform suggestion list lookup for the current value and validate. Use ajax when there is an url specified.
+ function _lookup (awe, val) {
+ var xhr
+ if (awe.utilprops.url) {
+ // are we still interested in this response?
+ if (_ifNeedListUpdate(awe, val, val)) {
+ xhr = new XMLHttpRequest()
+ awe.utilprops.ajax.call(awe,
+ awe.utilprops.url,
+ awe.utilprops.urlEnd,
+ awe.utilprops.loadall ? '' : val,
+ _onLoad.bind({awe: awe, xhr: xhr, queryVal: val}),
+ xhr
+ )
+ } else {
+ _matchValue(awe, awe.utilprops.prepop)
+ }
+ } else {
+ _matchValue(awe, awe.utilprops.prepop)
+ }
+ }
+
+ // Restart autocomplete search: clear css classes and send match-event with empty list.
+ function _restart (awe) {
+ var elem = awe.input
+ var classList = elem.classList
+ // IE11 only handles the first parameter of the remove method.
+ classList.remove(_CLS_NOT_FOUND)
+ classList.remove(_CLS_FOUND)
+ _fire(elem, _AWE_MATCH, [])
+ }
+
+ // handle new input value
+ function _update (awe, val, prepop) {
+ // prepop parameter is optional. Default value is false.
+ awe.utilprops.prepop = prepop || false
+ // if value changed
+ if (awe.utilprops.val !== val) {
+ // new value, clear previous selection
+ awe.utilprops.selected = null
+ // yes, user made a change
+ awe.utilprops.changed = true
+ awe.utilprops.val = val
+ // value is empty or smaller than minChars
+ if (val.length < awe.minChars || val.length === 0) {
+ // restart autocomplete search
+ _restart(awe)
+ }
+ if (val.length >= awe.minChars) {
+ // lookup suggestions and validate input
+ _lookup(awe, val)
+ }
+ }
+ return awe
+ }
+
+ // handle input changed event for THIS awesomplete object
+ function _onInput (e) {
+ var awe = this
+ var val
+ if (e.target === awe.input) {
+ // lowercase and trim input value
+ val = awe.utilprops.convertInput.call(awe, awe.input.value)
+ _update(awe, val)
+ }
+ }
+
+ // item function (as specified in Awesomplete) which just creates the 'li' HTML tag.
+ function _item (html /* , input */) {
+ return $.create('li', {
+ innerHTML: html,
+ 'aria-selected': 'false'
+ })
+ }
+
+ // Escape HTML characters in text.
+ function _htmlEscape (text) {
+ return text.replace('&', '&').replace('<', '<').replace('>', '>')
+ }
+
+ // Function to copy a field from the selected autocomplete item to another DOM element.
+ function _copyFun (e) {
+ var t = this
+ var sourceId = t.sourceId
+ var dataField = t.dataField
+ var targetId = t.targetId
+ var elem
+ var val
+ if (e.target === $(sourceId)) {
+ if (typeof targetId === 'function') {
+ targetId(e, dataField)
+ } else {
+ // lookup target element if it isn't resolved yet
+ elem = $(targetId)
+ // don't override target inputs if user is currently editing it.
+ if (elem && elem !== document.activeElement) {
+ // event must contain 1 item from suggestion list
+ val = Array.isArray(e.detail) && e.detail.length === 1 ? e.detail[0] : null
+ // if a datafield is specified, take that value
+ val = (dataField && val ? val[dataField] : val) || ''
+ // if it is an input control
+ if (typeof elem.value !== 'undefined') {
+ // set new value
+ elem.value = val
+ // not really sure if it is an input control, check if it has a classList
+ if (elem.classList && elem.classList.remove) {
+ // it might be another awesomplete control, if so the input is not wrong anymore because it's changed now
+ elem.classList.remove(_CLS_NOT_FOUND)
+ }
+ } else if (typeof elem.src !== 'undefined') { /* is it an image tag? */
+ elem.src = val
+ } else {
+ // use innerHTML to set the new value, because value might intentionally contain HTML markup
+ elem.innerHTML = val
+ }
+ }
+ }
+ }
+ }
+
+ // click function for the combobox button
+ function _clickFun (e) {
+ var t = this
+ var awe
+ var minChars
+ if (e.target === $(t.btnId)) {
+ e.preventDefault()
+ awe = t.awe
+ // toggle open/close
+ if (awe.ul.childNodes.length === 0 || awe.ul.hasAttribute('hidden')) {
+ minChars = awe.minChars
+ // ignore that the input value is empty
+ awe.minChars = 0
+ // show the suggestion list
+ awe.evaluate()
+ awe.minChars = minChars
+ } else {
+ awe.close()
+ }
+ }
+ }
+
+ // Return text with mark tags arround matching input. Don't replace inside tags.
+ // When startsWith is true, mark only the matching begin text.
+ function _mark (text, input, startsWith) {
+ var searchText = $.regExpEscape(_htmlEscape(input).trim())
+ var regExp = searchText.length <= 0 ? null : startsWith ? RegExp('^' + searchText, 'i') : RegExp('(?!<[^>]+?>)' + searchText + '(?![^<]*?>)', 'gi')
+ return text.replace(regExp, '$& ')
+ }
+
+ // Recursive jsonFlatten function
+ function _jsonFlatten (result, cur, prop, level, opts) {
+ var root = opts.root /* filter resulting json tree on root property (optional) */
+ var value = opts.value /* search for this property and copy it's value to a new 'value' property
+ (optional, do not specify it if the json array contains plain strings) */
+ var label = opts.label || opts.value /* search this property and copy it's value to a new 'label' property.
+ If there is a 'opts.value' field but no 'opts.label', assume label is the same. */
+ var isEmpty = true
+ var arrayResult = []
+ var j
+ // at top level, look if there is a property which starts with root (if specified)
+ if (level === 0 && root && prop && (prop + '.').lastIndexOf(root + '.', 0) !== 0 && (root + '.').lastIndexOf(prop + '.', 0) !== 0) {
+ return result
+ }
+ // handle current part of the json tree
+ if (Object(cur) !== cur) {
+ if (prop) {
+ result[prop] = cur
+ } else {
+ result = cur
+ }
+ } else if (Array.isArray(cur)) {
+ for (j = 0; j < cur.length; j++) {
+ arrayResult.push(_jsonFlatten({}, cur[j], '', level + 1, opts))
+ }
+ if (prop) {
+ result[prop] = arrayResult
+ } else {
+ result = arrayResult
+ }
+ } else {
+ for (j in cur) {
+ isEmpty = false
+ _jsonFlatten(result, cur[j], prop ? prop + '.' + j : j, level, opts)
+ }
+ if (isEmpty && prop) result[prop] = {}
+ }
+ // for arrays at top and subtop level
+ if (level < 2 && prop) {
+ // if a 'value' is specified and found a mathing property, create extra 'value' property.
+ if (value && (prop + '.').lastIndexOf(value + '.', 0) === 0) { result['value'] = result[prop] }
+ // if a 'label' is specified and found a mathing property, create extra 'label' property.
+ if (label && (prop + '.').lastIndexOf(label + '.', 0) === 0) { result['label'] = result[prop] }
+ }
+ if (level === 0) {
+ // Make sure that both value and label properties exist, even if they are nil.
+ // This is handy with limit 0 or 1 when the result doesn't have to contain an array.
+ if (value && !('value' in result)) { result['value'] = null }
+ if (label && !('label' in result)) { result['label'] = null }
+ }
+ return result
+ }
+
+ // Stop AwesompleteUtil; detach event handlers from the Awesomplete object.
+ function _detach () {
+ var t = this
+ var elem = t.awe.input
+ var boundMatch = t.boundMatch
+ var boundOnInput = t.boundOnInput
+ var boundOnKeydown = t.boundOnKeydown
+ var boundSelect = t.boundSelect
+
+ elem.removeEventListener(_AWE_SELECT, boundSelect)
+ elem.removeEventListener(_AWE_LOAD, boundMatch)
+ elem.removeEventListener(_AWE_CLOSE, boundMatch)
+ elem.removeEventListener('blur', boundMatch)
+ elem.removeEventListener('input', boundOnInput)
+ elem.removeEventListener('keydown', boundOnKeydown)
+ }
+
+ //
+ // public methods
+ //
+
+ return {
+
+ // ajax call for url + val + urlEnd. fn is the callback function. xhr parameter is optional.
+ ajax: function (url, urlEnd, val, fn, xhr) {
+ xhr = xhr || new XMLHttpRequest()
+ xhr.open('GET', url + encodeURIComponent(val) + (urlEnd || ''))
+ xhr.onload = fn
+ xhr.send()
+ return xhr
+ },
+
+ // Convert input before comparing it with suggestion. lowercase and trim the text
+ convertInput: function (text) {
+ return typeof text === 'string' ? text.trim().toLowerCase() : ''
+ },
+
+ // item function as defined in Awesomplete.
+ // item(html, input). input is optional and ignored in this implementation
+ item: _item,
+
+ // Set a new suggestion list. Trigger loadcomplete event.
+ // load(awesomplete, list, queryVal)
+ load: _loadComplete,
+
+ // Return text with mark tags arround matching input. Don't replace inside tags.
+ // When startsWith is true, mark only the matching begin text.
+ // mark(text, input, startsWith)
+ mark: _mark,
+
+ // highlight items: Marks input in the first line, not in the optional description
+ itemContains: function (text, input) {
+ var arr
+ if (input.trim().length > 0) {
+ arr = ('' + text).split(/
/)
+ arr[0] = _mark(arr[0], input)
+ text = arr.join('
')
+ }
+ return _item(text, input)
+ },
+
+ // highlight items: mark all occurrences of the input text
+ itemMarkAll: function (text, input) {
+ return _item(input.trim() === '' ? '' + text : _mark('' + text, input), input)
+ },
+
+ // highlight items: mark input in the begin text
+ itemStartsWith: function (text, input) {
+ return _item(input.trim() === '' ? '' + text : _mark('' + text, input, true), input)
+ },
+
+ // create Awesomplete object for input control elemId. opts are passed unchanged to Awesomplete.
+ create: function (elemId, utilOpts, opts) {
+ opts.item = opts.item || this.itemContains /* by default uses itemContains, can be overriden */
+ var awe = new Awesomplete(elemId, opts)
+ awe.utilprops = utilOpts || {}
+ // loadall is true if there is no url (there is a static data-list)
+ if (!awe.utilprops.url && typeof awe.utilprops.loadall === 'undefined') {
+ awe.utilprops.loadall = true
+ }
+ awe.utilprops.ajax = awe.utilprops.ajax || this.ajax /* default ajax function can be overriden */
+ awe.utilprops.convertInput = awe.utilprops.convertInput || this.convertInput /* the same applies for convertInput */
+ return awe
+ },
+
+ // attach Awesomplete object to event listeners
+ attach: function (awe) {
+ var elem = awe.input
+ var boundMatch = _match.bind(awe)
+ var boundOnKeydown = _onKeydown.bind(awe)
+ var boundOnInput = _onInput.bind(awe)
+ var boundSelect = _select.bind(awe)
+ var boundDetach = _detach.bind({awe: awe,
+ boundMatch: boundMatch,
+ boundOnInput: boundOnInput,
+ boundOnKeydown: boundOnKeydown,
+ boundSelect: boundSelect
+ })
+ var events = {
+ 'keydown': boundOnKeydown,
+ 'input': boundOnInput
+ }
+ events['blur'] = events[_AWE_CLOSE] = events[_AWE_LOAD] = boundMatch
+ events[_AWE_SELECT] = boundSelect
+ $.bind(elem, events)
+
+ awe.utilprops.detach = boundDetach
+ // Perform ajax call if prepop is true and there is an initial input value, or when all values must be loaded (loadall)
+ if (awe.utilprops.prepop && (awe.utilprops.loadall || elem.value.length > 0)) {
+ awe.utilprops.val = awe.utilprops.convertInput.call(awe, elem.value)
+ _lookup(awe, awe.utilprops.val)
+ }
+ return awe
+ },
+
+ // update input value via javascript. Use prepop=true when this is an initial/prepopulation value.
+ update: function (awe, value, prepop) {
+ awe.input.value = value
+ return _update(awe, value, prepop)
+ },
+
+ // create and attach Awesomplete object for input control elemId. opts are passed unchanged to Awesomplete.
+ start: function (elemId, utilOpts, opts) {
+ return this.attach(this.create(elemId, utilOpts, opts))
+ },
+
+ // Stop AwesompleteUtil; detach event handlers from the Awesomplete object.
+ detach: function (awe) {
+ if (awe.utilprops.detach) {
+ awe.utilprops.detach()
+ delete awe.utilprops.detach
+ }
+ return awe
+ },
+
+ // Create function to copy a field from the selected autocomplete item to another DOM element.
+ // dataField can be null.
+ createCopyFun: function (sourceId, dataField, targetId) {
+ return _copyFun.bind({sourceId: sourceId, dataField: dataField, targetId: $(targetId) || targetId})
+ },
+
+ // attach copy function to event listeners. prepop is optional and by default true.
+ // if true the copy function will also listen to awesomplete-prepop events.
+ // The optional listenEl is the element that listens, defaults to document.body.
+ attachCopyFun: function (fun, prepop, listenEl) {
+ // prepop parameter defaults to true
+ prepop = typeof prepop === 'boolean' ? prepop : true
+ listenEl = listenEl || document.body
+ listenEl.addEventListener(_AWE_MATCH, fun)
+ if (prepop) listenEl.addEventListener(_AWE_PREPOP, fun)
+ return fun
+ },
+
+ // Create and attach copy function.
+ startCopy: function (sourceId, dataField, targetId, prepop) {
+ var sourceEl = $(sourceId)
+ return this.attachCopyFun(this.createCopyFun(sourceEl || sourceId, dataField, targetId), prepop, sourceEl)
+ },
+
+ // Stop copy function. Detach it from event listeners.
+ // The optional listenEl must be the same element that was used during startCopy/attachCopyFun;
+ // in general: Awesomplete.$(sourceId). listenEl defaults to document.body.
+ detachCopyFun: function (fun, listenEl) {
+ listenEl = listenEl || document.body
+ listenEl.removeEventListener(_AWE_PREPOP, fun)
+ listenEl.removeEventListener(_AWE_MATCH, fun)
+ return fun
+ },
+
+ // Create function for combobox button (btnId) to toggle dropdown list.
+ createClickFun: function (btnId, awe) {
+ return _clickFun.bind({btnId: btnId, awe: awe})
+ },
+
+ // Attach click function for combobox to click event.
+ // The optional listenEl is the element that listens, defaults to document.body.
+ attachClickFun: function (fun, listenEl) {
+ listenEl = listenEl || document.body
+ listenEl.addEventListener('click', fun)
+ return fun
+ },
+
+ // Create and attach click function for combobox button. Toggles open/close of suggestion list.
+ startClick: function (btnId, awe) {
+ var btnEl = $(btnId)
+ return this.attachClickFun(this.createClickFun(btnEl || btnId, awe), btnEl)
+ },
+
+ // Stop click function. Detach it from event listeners.
+ // The optional listenEl must be the same element that was used during startClick/attachClickFun;
+ // in general: Awesomplete.$(btnId). listenEl defaults to document.body.
+ detachClickFun: function (fun, listenEl) {
+ listenEl = listenEl || document.body
+ listenEl.removeEventListener('click', fun)
+ return fun
+ },
+
+ // filter function as specified in Awesomplete. Filters suggestion list on items containing input value.
+ // Awesomplete.FILTER_CONTAINS filters on data.label, however
+ // this function filters on value and not on the shown label which may contain markup.
+ filterContains: function (data, input) {
+ return Awesomplete.FILTER_CONTAINS(data.value, input)
+ },
+
+ // filter function as specified in Awesomplete. Filters suggestion list on matching begin text.
+ // Awesomplete.FILTER_STARTSWITH filters on data.label, however
+ // this function filters on value and not on the shown label which may contain markup.
+ filterStartsWith: function (data, input) {
+ return Awesomplete.FILTER_STARTSWITH(data.value, input)
+ },
+
+ // Flatten JSON.
+ // { "a":{"b":{"c":[{"d":{"e":1}}]}}} becomes {"a.b.c":[{"d.e":1}]}.
+ // This function can be bind to configure it with extra options;
+ // bind({root: '', value: '', label: ''})
+ jsonFlatten: function (data) {
+ // start json tree recursion
+ return _jsonFlatten({}, data, '', 0, this)
+ }
+ }
+}())
diff --git a/apps/block_scout_web/assets/js/lib/awesomplete.js b/apps/block_scout_web/assets/js/lib/awesomplete.js
new file mode 100644
index 0000000000..3cf13d7921
--- /dev/null
+++ b/apps/block_scout_web/assets/js/lib/awesomplete.js
@@ -0,0 +1,2 @@
+import 'awesomplete/awesomplete.css'
+import 'awesomplete'
diff --git a/apps/block_scout_web/assets/js/lib/infinite_scroll_helpers.js b/apps/block_scout_web/assets/js/lib/infinite_scroll_helpers.js
index 45b278ae4d..b7fbb940a2 100644
--- a/apps/block_scout_web/assets/js/lib/infinite_scroll_helpers.js
+++ b/apps/block_scout_web/assets/js/lib/infinite_scroll_helpers.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import { connectElements } from './redux_helpers.js'
@@ -12,7 +12,7 @@ const initialState = {
function infiniteScrollReducer (state = initialState, action) {
switch (action.type) {
case 'INFINITE_SCROLL_ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'LOADING_NEXT_PAGE': {
return Object.assign({}, state, {
diff --git a/apps/block_scout_web/assets/js/lib/list_morph.js b/apps/block_scout_web/assets/js/lib/list_morph.js
index 175acb7c3f..6cdfea3e3f 100644
--- a/apps/block_scout_web/assets/js/lib/list_morph.js
+++ b/apps/block_scout_web/assets/js/lib/list_morph.js
@@ -1,5 +1,10 @@
import $ from 'jquery'
-import _ from 'lodash'
+import map from 'lodash/map'
+import get from 'lodash/get'
+import noop from 'lodash/noop'
+import find from 'lodash/find'
+import intersectionBy from 'lodash/intersectionBy'
+import differenceBy from 'lodash/differenceBy'
import morph from 'nanomorph'
import { updateAllAges } from './from_now'
@@ -25,12 +30,12 @@ import { updateAllAges } from './from_now'
export default function (container, newElements, { key, horizontal } = {}) {
if (!container) return
const oldElements = $(container).children().get()
- let currentList = _.map(oldElements, (el) => ({ id: _.get(el, key), el }))
- const newList = _.map(newElements, (el) => ({ id: _.get(el, key), el }))
- const overlap = _.intersectionBy(newList, currentList, 'id').map(({ id, el }) => ({ id, el: updateAllAges($(el))[0] }))
+ let currentList = map(oldElements, (el) => ({ id: get(el, key), el }))
+ const newList = map(newElements, (el) => ({ id: get(el, key), el }))
+ const overlap = intersectionBy(newList, currentList, 'id').map(({ id, el }) => ({ id, el: updateAllAges($(el))[0] }))
// remove old items
- const removals = _.differenceBy(currentList, newList, 'id')
+ const removals = differenceBy(currentList, newList, 'id')
let canAnimate = !horizontal && removals.length <= 1
removals.forEach(({ el }) => {
if (!canAnimate) return el.remove()
@@ -38,7 +43,7 @@ export default function (container, newElements, { key, horizontal } = {}) {
$el.addClass('shrink-out')
setTimeout(() => { slideUpRemove($el) }, 400)
})
- currentList = _.differenceBy(currentList, removals, 'id')
+ currentList = differenceBy(currentList, removals, 'id')
// update kept items
currentList = currentList.map(({ el }, i) => ({
@@ -47,14 +52,14 @@ export default function (container, newElements, { key, horizontal } = {}) {
}))
// add new items
- const finalList = newList.map(({ id, el }) => _.get(_.find(currentList, { id }), 'el', el)).reverse()
+ const finalList = newList.map(({ id, el }) => get(find(currentList, { id }), 'el', el)).reverse()
canAnimate = !horizontal
finalList.forEach((el, i) => {
if (el.parentElement) return
- if (!canAnimate) return container.insertBefore(el, _.get(finalList, `[${i - 1}]`))
+ if (!canAnimate) return container.insertBefore(el, get(finalList, `[${i - 1}]`))
canAnimate = false
- if (!_.get(finalList, `[${i - 1}]`)) return slideDownAppend($(container), el)
- slideDownBefore($(_.get(finalList, `[${i - 1}]`)), el)
+ if (!get(finalList, `[${i - 1}]`)) return slideDownAppend($(container), el)
+ slideDownBefore($(get(finalList, `[${i - 1}]`)), el)
})
}
@@ -80,7 +85,7 @@ function slideUpRemove ($el) {
})
}
-function smarterSlideDown ($el, { insert = _.noop } = {}) {
+function smarterSlideDown ($el, { insert = noop } = {}) {
if (!$el.length) return
const originalScrollHeight = document.body.scrollHeight
const scrollPosition = window.scrollY
@@ -100,7 +105,7 @@ function smarterSlideDown ($el, { insert = _.noop } = {}) {
}
}
-function smarterSlideUp ($el, { complete = _.noop } = {}) {
+function smarterSlideUp ($el, { complete = noop } = {}) {
if (!$el.length) return
const originalScrollHeight = document.body.scrollHeight
const scrollPosition = window.scrollY
diff --git a/apps/block_scout_web/assets/js/lib/market_history_chart.js b/apps/block_scout_web/assets/js/lib/market_history_chart.js
index 615f888d8a..098faac0a8 100644
--- a/apps/block_scout_web/assets/js/lib/market_history_chart.js
+++ b/apps/block_scout_web/assets/js/lib/market_history_chart.js
@@ -4,6 +4,7 @@ import humps from 'humps'
import numeral from 'numeral'
import { formatUsdValue } from '../lib/currency'
import sassVariables from '../../css/app.scss'
+import { showLoader } from '../lib/utils'
const config = {
type: 'line',
@@ -87,6 +88,17 @@ function getMarketCapData (marketHistoryData, availableSupply) {
}
}
+// colors for light and dark theme
+var priceLineColor
+var mcapLineColor
+if (localStorage.getItem('current-color-mode') === 'dark') {
+ priceLineColor = sassVariables.darkprimary
+ mcapLineColor = sassVariables.darksecondary
+} else {
+ priceLineColor = sassVariables.dashboardLineColorPrice
+ mcapLineColor = sassVariables.dashboardLineColorMarket
+}
+
class MarketHistoryChart {
constructor (el, availableSupply, marketHistoryData) {
this.price = {
@@ -95,8 +107,8 @@ class MarketHistoryChart {
data: getPriceData(marketHistoryData),
fill: false,
pointRadius: 0,
- backgroundColor: sassVariables.dashboardLineColorPrice,
- borderColor: sassVariables.dashboardLineColorPrice,
+ backgroundColor: priceLineColor,
+ borderColor: priceLineColor,
lineTension: 0
}
this.marketCap = {
@@ -105,8 +117,8 @@ class MarketHistoryChart {
data: getMarketCapData(marketHistoryData, availableSupply),
fill: false,
pointRadius: 0,
- backgroundColor: sassVariables.dashboardLineColorMarket,
- borderColor: sassVariables.dashboardLineColorMarket,
+ backgroundColor: mcapLineColor,
+ borderColor: mcapLineColor,
lineTension: 0
}
this.availableSupply = availableSupply
@@ -129,6 +141,10 @@ class MarketHistoryChart {
export function createMarketHistoryChart (el) {
const dataPath = el.dataset.market_history_chart_path
const $chartLoading = $('[data-chart-loading-message]')
+
+ const isTimeout = true
+ const timeoutID = showLoader(isTimeout, $chartLoading)
+
const $chartError = $('[data-chart-error-message]')
const chart = new MarketHistoryChart(el, 0, [])
$.getJSON(dataPath, {type: 'JSON'})
@@ -143,6 +159,7 @@ export function createMarketHistoryChart (el) {
})
.always(() => {
$chartLoading.hide()
+ clearTimeout(timeoutID)
})
return chart
}
diff --git a/apps/block_scout_web/assets/js/lib/redux_helpers.js b/apps/block_scout_web/assets/js/lib/redux_helpers.js
index fdf7c659b3..35dcc65b2c 100644
--- a/apps/block_scout_web/assets/js/lib/redux_helpers.js
+++ b/apps/block_scout_web/assets/js/lib/redux_helpers.js
@@ -1,5 +1,7 @@
import $ from 'jquery'
-import _ from 'lodash'
+import reduce from 'lodash/reduce'
+import isObject from 'lodash/isObject'
+import forIn from 'lodash/forIn'
import { createStore as reduxCreateStore } from 'redux'
/**
@@ -97,17 +99,17 @@ export function createStore (reducer) {
*/
export function connectElements ({ elements, store, action = 'ELEMENTS_LOAD' }) {
function loadElements () {
- return _.reduce(elements, (pageLoadParams, { load }, selector) => {
+ return reduce(elements, (pageLoadParams, { load }, selector) => {
if (!load) return pageLoadParams
const $el = $(selector)
if (!$el.length) return pageLoadParams
const morePageLoadParams = load($el, store)
- return _.isObject(morePageLoadParams) ? Object.assign(pageLoadParams, morePageLoadParams) : pageLoadParams
+ return isObject(morePageLoadParams) ? Object.assign(pageLoadParams, morePageLoadParams) : pageLoadParams
}, {})
}
function renderElements (state, oldState) {
- _.forIn(elements, ({ render }, selector) => {
+ forIn(elements, ({ render }, selector) => {
if (!render) return
const $el = $(selector)
if (!$el.length) return
diff --git a/apps/block_scout_web/assets/js/lib/utils.js b/apps/block_scout_web/assets/js/lib/utils.js
index d3bd6e84d1..e00d06ec1b 100644
--- a/apps/block_scout_web/assets/js/lib/utils.js
+++ b/apps/block_scout_web/assets/js/lib/utils.js
@@ -1,8 +1,8 @@
-import _ from 'lodash'
+import debounce from 'lodash/debounce'
export function batchChannel (func) {
let msgs = []
- const debouncedFunc = _.debounce(() => {
+ const debouncedFunc = debounce(() => {
func.apply(this, [msgs])
msgs = []
}, 1000, { maxWait: 5000 })
@@ -11,3 +11,16 @@ export function batchChannel (func) {
debouncedFunc()
}
}
+
+export function showLoader (isTimeout, loader) {
+ if (isTimeout) {
+ const timeout = setTimeout(function () {
+ loader.removeAttr('hidden')
+ loader.show()
+ }, 1000)
+ return timeout
+ } else {
+ loader.hide()
+ return null
+ }
+}
diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js
index 5b35a0b9d7..ddafbcb1e2 100644
--- a/apps/block_scout_web/assets/js/pages/address.js
+++ b/apps/block_scout_web/assets/js/pages/address.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import URI from 'urijs'
import humps from 'humps'
import numeral from 'numeral'
@@ -25,7 +25,7 @@ export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
diff --git a/apps/block_scout_web/assets/js/pages/address/coin_balances.js b/apps/block_scout_web/assets/js/pages/address/coin_balances.js
index 8c0100d3d2..b4523a6c64 100644
--- a/apps/block_scout_web/assets/js/pages/address/coin_balances.js
+++ b/apps/block_scout_web/assets/js/pages/address/coin_balances.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import socket from '../../socket'
import { connectElements } from '../../lib/redux_helpers.js'
@@ -14,7 +14,7 @@ export function reducer (state, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
diff --git a/apps/block_scout_web/assets/js/pages/address/internal_transactions.js b/apps/block_scout_web/assets/js/pages/address/internal_transactions.js
index aa95278c71..6c3d503256 100644
--- a/apps/block_scout_web/assets/js/pages/address/internal_transactions.js
+++ b/apps/block_scout_web/assets/js/pages/address/internal_transactions.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import numeral from 'numeral'
import socket from '../../socket'
@@ -20,7 +20,7 @@ export function reducer (state, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
diff --git a/apps/block_scout_web/assets/js/pages/address/logs.js b/apps/block_scout_web/assets/js/pages/address/logs.js
index 5b4cf8aecd..5c9bed9da2 100644
--- a/apps/block_scout_web/assets/js/pages/address/logs.js
+++ b/apps/block_scout_web/assets/js/pages/address/logs.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import { connectElements } from '../../lib/redux_helpers.js'
import { createAsyncLoadStore } from '../../lib/async_listing_load'
@@ -13,7 +13,7 @@ export function reducer (state, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'START_SEARCH': {
return Object.assign({}, state, {pagesStack: [], isSearch: true})
diff --git a/apps/block_scout_web/assets/js/pages/address/transactions.js b/apps/block_scout_web/assets/js/pages/address/transactions.js
index be70dcc3ba..ecd604e2d5 100644
--- a/apps/block_scout_web/assets/js/pages/address/transactions.js
+++ b/apps/block_scout_web/assets/js/pages/address/transactions.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import URI from 'urijs'
import humps from 'humps'
import { subscribeChannel } from '../../socket'
@@ -16,7 +16,7 @@ export function reducer (state, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
diff --git a/apps/block_scout_web/assets/js/pages/address/validations.js b/apps/block_scout_web/assets/js/pages/address/validations.js
index 6aca07a98b..d2456a183e 100644
--- a/apps/block_scout_web/assets/js/pages/address/validations.js
+++ b/apps/block_scout_web/assets/js/pages/address/validations.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import socket from '../../socket'
import { connectElements } from '../../lib/redux_helpers.js'
@@ -14,7 +14,7 @@ export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
return Object.assign({}, state, { channelDisconnected: true })
diff --git a/apps/block_scout_web/assets/js/pages/blocks.js b/apps/block_scout_web/assets/js/pages/blocks.js
index 2103c18a89..4d9bdc05d9 100644
--- a/apps/block_scout_web/assets/js/pages/blocks.js
+++ b/apps/block_scout_web/assets/js/pages/blocks.js
@@ -1,5 +1,10 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
+import last from 'lodash/last'
+import min from 'lodash/min'
+import max from 'lodash/max'
+import keys from 'lodash/keys'
+import rangeRight from 'lodash/rangeRight'
import humps from 'humps'
import socket from '../socket'
import { connectElements } from '../lib/redux_helpers.js'
@@ -14,7 +19,7 @@ export const blockReducer = withMissingBlocks(baseReducer)
function baseReducer (state = initialState, action) {
switch (action.type) {
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
return Object.assign({}, state, {
@@ -25,7 +30,7 @@ function baseReducer (state = initialState, action) {
if (state.channelDisconnected || state.beyondPageOne || state.blockType !== 'block') return state
const blockNumber = getBlockNumber(action.msg.blockHtml)
- const minBlock = getBlockNumber(_.last(state.items))
+ const minBlock = getBlockNumber(last(state.items))
if (state.items.length && blockNumber < minBlock) return state
@@ -62,12 +67,12 @@ function withMissingBlocks (reducer) {
return acc
}, {})
- const blockNumbers = _(blockNumbersToItems).keys().map(x => parseInt(x, 10)).value()
- const minBlock = _.min(blockNumbers)
- const maxBlock = _.max(blockNumbers)
+ const blockNumbers = keys(blockNumbersToItems).map(x => parseInt(x, 10))
+ const minBlock = min(blockNumbers)
+ const maxBlock = max(blockNumbers)
return Object.assign({}, result, {
- items: _.rangeRight(minBlock, maxBlock + 1)
+ items: rangeRight(minBlock, maxBlock + 1)
.map((blockNumber) => blockNumbersToItems[blockNumber] || placeHolderBlock(blockNumber))
})
}
diff --git a/apps/block_scout_web/assets/js/pages/chain.js b/apps/block_scout_web/assets/js/pages/chain.js
index f4cd0e6628..df89d92f36 100644
--- a/apps/block_scout_web/assets/js/pages/chain.js
+++ b/apps/block_scout_web/assets/js/pages/chain.js
@@ -1,11 +1,15 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
+import first from 'lodash/first'
+import rangeRight from 'lodash/rangeRight'
+import find from 'lodash/find'
+import map from 'lodash/map'
import humps from 'humps'
import numeral from 'numeral'
import socket from '../socket'
import { exchangeRateChannel, formatUsdValue } from '../lib/currency'
import { createStore, connectElements } from '../lib/redux_helpers.js'
-import { batchChannel } from '../lib/utils'
+import { batchChannel, showLoader } from '../lib/utils'
import listMorph from '../lib/list_morph'
import { createMarketHistoryChart } from '../lib/market_history_chart'
@@ -33,7 +37,7 @@ export const reducer = withMissingBlocks(baseReducer)
function baseReducer (state = initialState, action) {
switch (action.type) {
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'RECEIVED_NEW_ADDRESS_COUNT': {
return Object.assign({}, state, {
@@ -122,12 +126,12 @@ function withMissingBlocks (reducer) {
if (!result.blocks || result.blocks.length < 2) return result
- const maxBlock = _.first(result.blocks).blockNumber
+ const maxBlock = first(result.blocks).blockNumber
const minBlock = maxBlock - (result.blocks.length - 1)
return Object.assign({}, result, {
- blocks: _.rangeRight(minBlock, maxBlock + 1)
- .map((blockNumber) => _.find(result.blocks, ['blockNumber', blockNumber]) || {
+ blocks: rangeRight(minBlock, maxBlock + 1)
+ .map((blockNumber) => find(result.blocks, ['blockNumber', blockNumber]) || {
blockNumber,
chainBlockHtml: placeHolderBlock(blockNumber)
})
@@ -194,7 +198,7 @@ const elements = {
const container = $el[0]
if (state.blocksLoading === false) {
- const blocks = _.map(state.blocks, ({ chainBlockHtml }) => $(chainBlockHtml)[0])
+ const blocks = map(state.blocks, ({ chainBlockHtml }) => $(chainBlockHtml)[0])
listMorph(container, blocks, { key: 'dataset.blockNumber', horizontal: true })
}
}
@@ -210,11 +214,7 @@ const elements = {
},
'[data-selector="chain-block-list"] [data-selector="loading-message"]': {
render ($el, state, oldState) {
- if (state.blocksLoading) {
- $el.show()
- } else {
- $el.hide()
- }
+ showLoader(state.blocksLoading, $el)
}
},
'[data-selector="transactions-list"] [data-selector="error-message"]': {
@@ -224,7 +224,7 @@ const elements = {
},
'[data-selector="transactions-list"] [data-selector="loading-message"]': {
render ($el, state, oldState) {
- $el.toggle(state.transactionsLoading)
+ showLoader(state.transactionsLoading, $el)
}
},
'[data-selector="transactions-list"]': {
@@ -234,7 +234,7 @@ const elements = {
render ($el, state, oldState) {
if (oldState.transactions === state.transactions) return
const container = $el[0]
- const newElements = _.map(state.transactions, ({ transactionHtml }) => $(transactionHtml)[0])
+ const newElements = map(state.transactions, ({ transactionHtml }) => $(transactionHtml)[0])
listMorph(container, newElements, { key: 'dataset.identifierHash' })
}
},
diff --git a/apps/block_scout_web/assets/js/pages/dark-mode-switcher.js b/apps/block_scout_web/assets/js/pages/dark-mode-switcher.js
new file mode 100644
index 0000000000..e9e0bdc524
--- /dev/null
+++ b/apps/block_scout_web/assets/js/pages/dark-mode-switcher.js
@@ -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)
+})
diff --git a/apps/block_scout_web/assets/js/pages/pending_transactions.js b/apps/block_scout_web/assets/js/pages/pending_transactions.js
index 1cbb5d47d0..711f7c4343 100644
--- a/apps/block_scout_web/assets/js/pages/pending_transactions.js
+++ b/apps/block_scout_web/assets/js/pages/pending_transactions.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import numeral from 'numeral'
import socket from '../socket'
@@ -20,7 +20,7 @@ export const initialState = {
export function reducer (state = initialState, action) {
switch (action.type) {
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
return Object.assign({}, state, {
diff --git a/apps/block_scout_web/assets/js/pages/transaction.js b/apps/block_scout_web/assets/js/pages/transaction.js
index cd247d530a..139d1f527c 100644
--- a/apps/block_scout_web/assets/js/pages/transaction.js
+++ b/apps/block_scout_web/assets/js/pages/transaction.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import numeral from 'numeral'
import socket from '../socket'
@@ -13,7 +13,7 @@ export const initialState = {
export function reducer (state = initialState, action) {
switch (action.type) {
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'RECEIVED_NEW_BLOCK': {
if ((action.msg.blockNumber - state.blockNumber) > state.confirmations) {
diff --git a/apps/block_scout_web/assets/js/pages/transactions.js b/apps/block_scout_web/assets/js/pages/transactions.js
index a6c038166b..f528f760c4 100644
--- a/apps/block_scout_web/assets/js/pages/transactions.js
+++ b/apps/block_scout_web/assets/js/pages/transactions.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import humps from 'humps'
import numeral from 'numeral'
import socket from '../socket'
@@ -18,7 +18,7 @@ export const initialState = {
export function reducer (state = initialState, action) {
switch (action.type) {
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
return Object.assign({}, state, {
diff --git a/apps/block_scout_web/assets/js/pages/verification_form.js b/apps/block_scout_web/assets/js/pages/verification_form.js
index 619a8e1326..10504c144c 100644
--- a/apps/block_scout_web/assets/js/pages/verification_form.js
+++ b/apps/block_scout_web/assets/js/pages/verification_form.js
@@ -1,5 +1,5 @@
import $ from 'jquery'
-import _ from 'lodash'
+import omit from 'lodash/omit'
import URI from 'urijs'
import humps from 'humps'
import { subscribeChannel } from '../socket'
@@ -15,7 +15,7 @@ export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
- return Object.assign({}, state, _.omit(action, 'type'))
+ return Object.assign({}, state, omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
diff --git a/apps/block_scout_web/assets/package-lock.json b/apps/block_scout_web/assets/package-lock.json
index 22c6d216de..23f1ccb7ba 100644
--- a/apps/block_scout_web/assets/package-lock.json
+++ b/apps/block_scout_web/assets/package-lock.json
@@ -46,6 +46,12 @@
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.1.0.tgz",
"integrity": "sha512-0XHj3cIq7OiG2v79UldqDHLFndLXxq0hbNTvsi7zDbLXiBtMkX+exuVUX466cajlSV8rkLiwa7GhTcMIKR1ajQ=="
},
+ "@types/q": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz",
+ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
+ "dev": true
+ },
"@webassemblyjs/ast": {
"version": "1.5.12",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.12.tgz",
@@ -377,6 +383,12 @@
"json-schema-traverse": "^0.3.0"
}
},
+ "ajv-errors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+ "dev": true
+ },
"ajv-keywords": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
@@ -648,6 +660,11 @@
"postcss-value-parser": "^3.2.3"
}
},
+ "awesomplete": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/awesomplete/-/awesomplete-1.1.2.tgz",
+ "integrity": "sha1-tuJT9zR05GJ4u6Wuf4HUJiFg+3U="
+ },
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
@@ -1492,6 +1509,12 @@
"integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
"dev": true
},
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
"bootstrap": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz",
@@ -1727,6 +1750,23 @@
"unset-value": "^1.0.0"
}
},
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "dev": true,
+ "requires": {
+ "callsites": "^2.0.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ }
+ }
+ },
"caller-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
@@ -1742,6 +1782,12 @@
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
"dev": true
},
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
"camelcase-keys": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
@@ -1760,36 +1806,6 @@
}
}
},
- "caniuse-api": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz",
- "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=",
- "dev": true,
- "requires": {
- "browserslist": "^1.3.6",
- "caniuse-db": "^1.0.30000529",
- "lodash.memoize": "^4.1.2",
- "lodash.uniq": "^4.5.0"
- },
- "dependencies": {
- "browserslist": {
- "version": "1.7.7",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
- "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
- "dev": true,
- "requires": {
- "caniuse-db": "^1.0.30000639",
- "electron-to-chromium": "^1.2.7"
- }
- }
- }
- },
- "caniuse-db": {
- "version": "1.0.30000862",
- "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000862.tgz",
- "integrity": "sha1-bB4pb4u+Xl6kbwQhXouQ7Y+52o0=",
- "dev": true
- },
"caniuse-lite": {
"version": "1.0.30000862",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000862.tgz",
@@ -1912,42 +1928,6 @@
"integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
"dev": true
},
- "clap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz",
- "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- }
- },
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@@ -1996,12 +1976,6 @@
"tiny-emitter": "^2.0.0"
}
},
- "clone": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
- "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
- "dev": true
- },
"clone-deep": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
@@ -2028,15 +2002,6 @@
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true
},
- "coa": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz",
- "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=",
- "dev": true,
- "requires": {
- "q": "^1.1.2"
- }
- },
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -2053,34 +2018,6 @@
"object-visit": "^1.0.0"
}
},
- "color": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz",
- "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=",
- "dev": true,
- "requires": {
- "clone": "^1.0.2",
- "color-convert": "^1.3.0",
- "color-string": "^0.3.0"
- },
- "dependencies": {
- "color-convert": {
- "version": "1.9.2",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
- "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.1"
- }
- },
- "color-name": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
- "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
- "dev": true
- }
- }
- },
"color-convert": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
@@ -2091,32 +2028,6 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
- "color-string": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz",
- "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=",
- "dev": true,
- "requires": {
- "color-name": "^1.0.0"
- }
- },
- "colormin": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz",
- "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=",
- "dev": true,
- "requires": {
- "color": "^0.11.0",
- "css-color-names": "0.0.4",
- "has": "^1.0.1"
- }
- },
- "colors": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
- "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
- "dev": true
- },
"combined-stream": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
@@ -2340,700 +2251,1319 @@
"integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
"dev": true
},
- "css-loader": {
- "version": "0.28.11",
- "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz",
- "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==",
+ "css-declaration-sorter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz",
+ "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==",
"dev": true,
"requires": {
- "babel-code-frame": "^6.26.0",
- "css-selector-tokenizer": "^0.7.0",
- "cssnano": "^3.10.0",
- "icss-utils": "^2.1.0",
- "loader-utils": "^1.0.2",
- "lodash.camelcase": "^4.3.0",
- "object-assign": "^4.1.1",
- "postcss": "^5.0.6",
- "postcss-modules-extract-imports": "^1.2.0",
- "postcss-modules-local-by-default": "^1.2.0",
- "postcss-modules-scope": "^1.1.0",
- "postcss-modules-values": "^1.3.0",
- "postcss-value-parser": "^3.3.0",
- "source-list-map": "^2.0.0"
+ "postcss": "^7.0.1",
+ "timsort": "^0.3.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "css-selector-tokenizer": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
- "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
- "dev": true,
- "requires": {
- "cssesc": "^0.1.0",
- "fastparse": "^1.1.1",
- "regexpu-core": "^1.0.0"
+ "css-loader": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.1.0.tgz",
+ "integrity": "sha512-MuL8WsF/KSrHCBCYaozBKlx+r7vIfUaDTEreo7wR7Vv3J6N0z6fqWjRk3e/6wjneitXN1r/Y9FTK1psYNOBdJQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "cssesc": "^3.0.0",
+ "icss-utils": "^4.1.1",
+ "loader-utils": "^1.2.3",
+ "normalize-path": "^3.0.0",
+ "postcss": "^7.0.17",
+ "postcss-modules-extract-imports": "^2.0.0",
+ "postcss-modules-local-by-default": "^3.0.2",
+ "postcss-modules-scope": "^2.1.0",
+ "postcss-modules-values": "^3.0.0",
+ "postcss-value-parser": "^4.0.0",
+ "schema-utils": "^2.0.0"
},
"dependencies": {
- "regexpu-core": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
- "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
"dev": true,
"requires": {
- "regenerate": "^1.2.1",
- "regjsgen": "^0.2.0",
- "regjsparser": "^0.1.4"
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
}
- }
- }
- },
- "cssesc": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
- "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
- "dev": true
- },
- "cssnano": {
- "version": "3.10.0",
- "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz",
- "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=",
- "dev": true,
- "requires": {
- "autoprefixer": "^6.3.1",
- "decamelize": "^1.1.2",
- "defined": "^1.0.0",
- "has": "^1.0.1",
- "object-assign": "^4.0.1",
- "postcss": "^5.0.14",
- "postcss-calc": "^5.2.0",
- "postcss-colormin": "^2.1.8",
- "postcss-convert-values": "^2.3.4",
- "postcss-discard-comments": "^2.0.4",
- "postcss-discard-duplicates": "^2.0.1",
- "postcss-discard-empty": "^2.0.1",
- "postcss-discard-overridden": "^0.1.1",
- "postcss-discard-unused": "^2.2.1",
- "postcss-filter-plugins": "^2.0.0",
- "postcss-merge-idents": "^2.1.5",
- "postcss-merge-longhand": "^2.0.1",
- "postcss-merge-rules": "^2.0.3",
- "postcss-minify-font-values": "^1.0.2",
- "postcss-minify-gradients": "^1.0.1",
- "postcss-minify-params": "^1.0.4",
- "postcss-minify-selectors": "^2.0.4",
- "postcss-normalize-charset": "^1.1.0",
- "postcss-normalize-url": "^3.0.7",
- "postcss-ordered-values": "^2.1.0",
- "postcss-reduce-idents": "^2.2.2",
- "postcss-reduce-initial": "^1.0.0",
- "postcss-reduce-transforms": "^1.0.3",
- "postcss-svgo": "^2.1.1",
- "postcss-unique-selectors": "^2.0.2",
- "postcss-value-parser": "^3.2.3",
- "postcss-zindex": "^2.0.1"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true
},
- "autoprefixer": {
- "version": "6.7.7",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz",
- "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=",
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "browserslist": "^1.7.6",
- "caniuse-db": "^1.0.30000634",
- "normalize-range": "^0.1.2",
- "num2fraction": "^1.2.2",
- "postcss": "^5.2.16",
- "postcss-value-parser": "^3.2.3"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
}
},
- "browserslist": {
- "version": "1.7.7",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
- "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"requires": {
- "caniuse-db": "^1.0.30000639",
- "electron-to-chromium": "^1.2.7"
+ "minimist": "^1.2.0"
}
},
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "postcss-value-parser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz",
+ "integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==",
"dev": true
},
+ "schema-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.0.1.tgz",
+ "integrity": "sha512-HJFKJ4JixDpRur06QHwi8uu2kZbng318ahWEKgBjc0ZklcE4FDvmm2wghb448q0IRaABxIESt8vqPFvwgMB80A==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "csso": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz",
- "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=",
+ "css-select": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz",
+ "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==",
"dev": true,
"requires": {
- "clap": "^1.0.9",
- "source-map": "^0.5.3"
- },
- "dependencies": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- }
- }
- },
- "cssom": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz",
- "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==",
- "dev": true
- },
- "cssstyle": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz",
- "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==",
- "dev": true,
- "requires": {
- "cssom": "0.3.x"
- }
- },
- "currently-unhandled": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
- "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
- "dev": true,
- "requires": {
- "array-find-index": "^1.0.1"
+ "boolbase": "^1.0.0",
+ "css-what": "^2.1.2",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
}
},
- "cyclist": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
- "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+ "css-select-base-adapter": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
+ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
"dev": true
},
- "dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
- "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
- "dev": true,
- "requires": {
- "assert-plus": "^1.0.0"
- }
- },
- "data-urls": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
- "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
+ "css-tree": {
+ "version": "1.0.0-alpha.33",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.33.tgz",
+ "integrity": "sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w==",
"dev": true,
"requires": {
- "abab": "^2.0.0",
- "whatwg-mimetype": "^2.2.0",
- "whatwg-url": "^7.0.0"
+ "mdn-data": "2.0.4",
+ "source-map": "^0.5.3"
},
"dependencies": {
- "whatwg-url": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
- "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
- "dev": true,
- "requires": {
- "lodash.sortby": "^4.7.0",
- "tr46": "^1.0.1",
- "webidl-conversions": "^4.0.2"
- }
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
}
}
},
- "date-now": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
- "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
- "dev": true
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
- },
- "decode-uri-component": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
- "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "css-unit-converter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz",
+ "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=",
"dev": true
},
- "deep-is": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
- "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "css-what": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
"dev": true
},
- "default-require-extensions": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
- "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=",
- "dev": true,
- "requires": {
- "strip-bom": "^2.0.0"
+ "cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true
+ },
+ "cssnano-preset-default": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz",
+ "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==",
+ "dev": true,
+ "requires": {
+ "css-declaration-sorter": "^4.0.1",
+ "cssnano-util-raw-cache": "^4.0.1",
+ "postcss": "^7.0.0",
+ "postcss-calc": "^7.0.1",
+ "postcss-colormin": "^4.0.3",
+ "postcss-convert-values": "^4.0.1",
+ "postcss-discard-comments": "^4.0.2",
+ "postcss-discard-duplicates": "^4.0.2",
+ "postcss-discard-empty": "^4.0.1",
+ "postcss-discard-overridden": "^4.0.1",
+ "postcss-merge-longhand": "^4.0.11",
+ "postcss-merge-rules": "^4.0.3",
+ "postcss-minify-font-values": "^4.0.2",
+ "postcss-minify-gradients": "^4.0.2",
+ "postcss-minify-params": "^4.0.2",
+ "postcss-minify-selectors": "^4.0.2",
+ "postcss-normalize-charset": "^4.0.1",
+ "postcss-normalize-display-values": "^4.0.2",
+ "postcss-normalize-positions": "^4.0.2",
+ "postcss-normalize-repeat-style": "^4.0.2",
+ "postcss-normalize-string": "^4.0.2",
+ "postcss-normalize-timing-functions": "^4.0.2",
+ "postcss-normalize-unicode": "^4.0.1",
+ "postcss-normalize-url": "^4.0.1",
+ "postcss-normalize-whitespace": "^4.0.2",
+ "postcss-ordered-values": "^4.1.2",
+ "postcss-reduce-initial": "^4.0.3",
+ "postcss-reduce-transforms": "^4.0.2",
+ "postcss-svgo": "^4.0.2",
+ "postcss-unique-selectors": "^4.0.1"
},
"dependencies": {
- "strip-bom": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
- "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "browserslist": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
+ "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
"dev": true,
"requires": {
- "is-utf8": "^0.2.0"
+ "caniuse-lite": "^1.0.30000984",
+ "electron-to-chromium": "^1.3.191",
+ "node-releases": "^1.1.25"
}
- }
- }
- },
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ },
+ "caniuse-api": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
"dev": true,
"requires": {
- "kind-of": "^6.0.0"
+ "browserslist": "^4.0.0",
+ "caniuse-lite": "^1.0.0",
+ "lodash.memoize": "^4.1.2",
+ "lodash.uniq": "^4.5.0"
}
},
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "caniuse-lite": {
+ "version": "1.0.30000985",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz",
+ "integrity": "sha512-1ngiwkgqAYPG0JSSUp3PUDGPKKY59EK7NrGGX+VOxaKCNzRbNc7uXMny+c3VJfZxtoK3wSImTvG9T9sXiTw2+w==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "kind-of": "^6.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
}
},
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "coa": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
+ "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
"dev": true,
"requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
+ "@types/q": "^1.5.1",
+ "chalk": "^2.4.1",
+ "q": "^1.1.2"
}
},
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "color": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz",
+ "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.1",
+ "color-string": "^1.5.2"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-string": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
+ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+ "dev": true,
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "cssesc": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+ "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==",
"dev": true
- }
- }
- },
- "defined": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
- "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
- "dev": true
- },
- "del": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
- "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
- "dev": true,
- "requires": {
- "globby": "^5.0.0",
- "is-path-cwd": "^1.0.0",
- "is-path-in-cwd": "^1.0.0",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "rimraf": "^2.2.8"
- },
- "dependencies": {
- "globby": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
- "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ },
+ "csso": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
+ "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==",
"dev": true,
"requires": {
- "array-union": "^1.0.1",
- "arrify": "^1.0.0",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
+ "css-tree": "1.0.0-alpha.29"
+ },
+ "dependencies": {
+ "css-tree": {
+ "version": "1.0.0-alpha.29",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
+ "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==",
+ "dev": true,
+ "requires": {
+ "mdn-data": "~1.1.0",
+ "source-map": "^0.5.3"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
}
},
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "electron-to-chromium": {
+ "version": "1.3.200",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz",
+ "integrity": "sha512-PUurrpyDA74MuAjJRD+79ss5BqJlU3mdArRbuu4wO/dt6jc3Ic/6BDmFJxkdwbfq39cHf/XKm2vW98XSvut9Dg==",
"dev": true
- }
- }
- },
- "delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
- "dev": true
- },
- "delegate": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
- "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
- },
- "delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
- "dev": true
- },
- "des.js": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
- "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
- }
- },
- "detect-indent": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
- "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
- "dev": true,
- "requires": {
- "repeating": "^2.0.0"
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "is-svg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz",
+ "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==",
+ "dev": true,
+ "requires": {
+ "html-comment-regex": "^1.1.0"
+ }
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "mdn-data": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz",
+ "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
+ "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-calc": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz",
+ "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==",
+ "dev": true,
+ "requires": {
+ "css-unit-converter": "^1.1.1",
+ "postcss": "^7.0.5",
+ "postcss-selector-parser": "^5.0.0-rc.4",
+ "postcss-value-parser": "^3.3.1"
+ }
+ },
+ "postcss-colormin": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz",
+ "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "color": "^3.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-convert-values": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz",
+ "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-discard-comments": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz",
+ "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-discard-duplicates": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz",
+ "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-discard-empty": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz",
+ "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-discard-overridden": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz",
+ "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-merge-longhand": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz",
+ "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==",
+ "dev": true,
+ "requires": {
+ "css-color-names": "0.0.4",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "stylehacks": "^4.0.0"
+ }
+ },
+ "postcss-merge-rules": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz",
+ "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-api": "^3.0.0",
+ "cssnano-util-same-parent": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0",
+ "vendors": "^1.0.0"
+ },
+ "dependencies": {
+ "postcss-selector-parser": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz",
+ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.1",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-minify-font-values": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz",
+ "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-minify-gradients": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz",
+ "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "is-color-stop": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-minify-params": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz",
+ "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "browserslist": "^4.0.0",
+ "cssnano-util-get-arguments": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "uniqs": "^2.0.0"
+ }
+ },
+ "postcss-minify-selectors": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz",
+ "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss-selector-parser": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz",
+ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.1",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-normalize-charset": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz",
+ "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-normalize-url": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz",
+ "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==",
+ "dev": true,
+ "requires": {
+ "is-absolute-url": "^2.0.0",
+ "normalize-url": "^3.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-ordered-values": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz",
+ "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-reduce-initial": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz",
+ "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-api": "^3.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-reduce-transforms": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz",
+ "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^2.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "postcss-svgo": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz",
+ "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==",
+ "dev": true,
+ "requires": {
+ "is-svg": "^3.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "svgo": "^1.0.0"
+ }
+ },
+ "postcss-unique-selectors": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz",
+ "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "postcss": "^7.0.0",
+ "uniqs": "^2.0.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "svgo": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.0.tgz",
+ "integrity": "sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "coa": "^2.0.2",
+ "css-select": "^2.0.0",
+ "css-select-base-adapter": "^0.1.1",
+ "css-tree": "1.0.0-alpha.33",
+ "csso": "^3.5.1",
+ "js-yaml": "^3.13.1",
+ "mkdirp": "~0.5.1",
+ "object.values": "^1.1.0",
+ "sax": "~1.2.4",
+ "stable": "^0.1.8",
+ "unquote": "~1.1.1",
+ "util.promisify": "~1.0.0"
+ }
+ }
}
},
- "detect-newline": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
- "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
+ "cssnano-util-get-arguments": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz",
+ "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=",
"dev": true
},
- "diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "cssnano-util-get-match": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz",
+ "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=",
"dev": true
},
- "diffie-hellman": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
- "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "cssnano-util-raw-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz",
+ "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==",
"dev": true,
"requires": {
- "bn.js": "^4.1.0",
- "miller-rabin": "^4.0.0",
- "randombytes": "^2.0.0"
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
}
},
- "dir-glob": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
- "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
+ "cssnano-util-same-parent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz",
+ "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==",
+ "dev": true
+ },
+ "cssom": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz",
+ "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==",
+ "dev": true
+ },
+ "cssstyle": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz",
+ "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==",
"dev": true,
"requires": {
- "arrify": "^1.0.1",
- "path-type": "^3.0.0"
+ "cssom": "0.3.x"
}
},
- "doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
"dev": true,
"requires": {
- "esutils": "^2.0.2"
+ "array-find-index": "^1.0.1"
}
},
- "domain-browser": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
- "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "cyclist": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
"dev": true
},
- "domexception": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
- "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"dev": true,
"requires": {
- "webidl-conversions": "^4.0.2"
+ "assert-plus": "^1.0.0"
}
},
- "duplexify": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
- "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
+ "data-urls": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
+ "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
"dev": true,
"requires": {
- "end-of-stream": "^1.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0",
- "stream-shift": "^1.0.0"
- }
- },
- "ecc-jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
- "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
- "dev": true,
- "optional": true,
- "requires": {
- "jsbn": "~0.1.0"
+ "abab": "^2.0.0",
+ "whatwg-mimetype": "^2.2.0",
+ "whatwg-url": "^7.0.0"
+ },
+ "dependencies": {
+ "whatwg-url": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
+ "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^1.0.1",
+ "webidl-conversions": "^4.0.2"
+ }
+ }
}
},
- "electron-to-chromium": {
- "version": "1.3.50",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz",
- "integrity": "sha1-dDi3b5K0G5GfP73TUPvQdX2s3fc=",
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
"dev": true
},
- "elliptic": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
- "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
- "bn.js": "^4.4.0",
- "brorand": "^1.0.1",
- "hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.0"
+ "ms": "2.0.0"
}
},
- "emojis-list": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
- "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
- "end-of-stream": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
- "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "default-require-extensions": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
+ "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=",
"dev": true,
"requires": {
- "once": "^1.4.0"
+ "strip-bom": "^2.0.0"
+ },
+ "dependencies": {
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ }
}
},
- "enhanced-resolve": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
- "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"dev": true,
"requires": {
- "graceful-fs": "^4.1.2",
- "memory-fs": "^0.4.0",
- "tapable": "^1.0.0"
+ "object-keys": "^1.0.12"
}
},
- "errno": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
- "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
"dev": true,
"requires": {
- "prr": "~1.0.1"
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ }
}
},
- "error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
"dev": true,
"requires": {
- "is-arrayish": "^0.2.1"
+ "globby": "^5.0.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "rimraf": "^2.2.8"
+ },
+ "dependencies": {
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
}
},
- "es-abstract": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
- "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
"dev": true,
"requires": {
- "es-to-primitive": "^1.1.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.1",
- "is-callable": "^1.1.3",
- "is-regex": "^1.0.4"
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
}
},
- "es-to-primitive": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
- "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
"dev": true,
"requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
+ "repeating": "^2.0.0"
}
},
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "detect-newline": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
"dev": true
},
- "escodegen": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz",
- "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==",
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"dev": true,
"requires": {
- "esprima": "^3.1.3",
- "estraverse": "^4.2.0",
- "esutils": "^2.0.2",
- "optionator": "^0.8.1",
- "source-map": "~0.6.1"
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "dir-glob": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
+ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "path-type": "^3.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+ "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "entities": "^1.1.1"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domexception": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
+ "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
+ "dev": true,
+ "requires": {
+ "webidl-conversions": "^4.0.2"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "duplexify": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
+ "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "~0.1.0"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.3.50",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz",
+ "integrity": "sha1-dDi3b5K0G5GfP73TUPvQdX2s3fc=",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "dev": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
+ "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.1.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.1",
+ "is-callable": "^1.1.3",
+ "is-regex": "^1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "escodegen": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz",
+ "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==",
+ "dev": true,
+ "requires": {
+ "esprima": "^3.1.3",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.6.1"
},
"dependencies": {
"esprima": {
@@ -3558,18 +4088,6 @@
}
}
},
- "extract-text-webpack-plugin": {
- "version": "4.0.0-beta.0",
- "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz",
- "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==",
- "dev": true,
- "requires": {
- "async": "^2.4.1",
- "loader-utils": "^1.1.0",
- "schema-utils": "^0.4.5",
- "webpack-sources": "^1.1.0"
- }
- },
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -3594,12 +4112,6 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
- "fastparse": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
- "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=",
- "dev": true
- },
"fb-watchman": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz",
@@ -3609,6 +4121,12 @@
"bser": "^2.0.0"
}
},
+ "figgy-pudding": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+ "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
+ "dev": true
+ },
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
@@ -3709,12 +4227,6 @@
"write": "^0.2.1"
}
},
- "flatten": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
- "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
- "dev": true
- },
"flush-write-stream": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
@@ -3816,7 +4328,8 @@
"version": "2.1.1",
"resolved": false,
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -3840,13 +4353,15 @@
"version": "1.0.0",
"resolved": false,
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -3863,19 +4378,22 @@
"version": "1.1.0",
"resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": false,
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": false,
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -4006,7 +4524,8 @@
"version": "2.0.3",
"resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -4020,6 +4539,7 @@
"resolved": false,
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -4036,6 +4556,7 @@
"resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -4044,13 +4565,15 @@
"version": "0.0.8",
"resolved": false,
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.2.4",
"resolved": false,
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -4071,6 +4594,7 @@
"resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -4159,7 +4683,8 @@
"version": "1.0.1",
"resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -4173,6 +4698,7 @@
"resolved": false,
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -4268,7 +4794,8 @@
"version": "5.1.1",
"resolved": false,
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -4310,6 +4837,7 @@
"resolved": false,
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -4331,6 +4859,7 @@
"resolved": false,
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -4379,13 +4908,15 @@
"version": "1.0.2",
"resolved": false,
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.2",
"resolved": false,
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -4737,6 +5268,12 @@
"minimalistic-assert": "^1.0.0"
}
},
+ "hex-color-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
+ "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
+ "dev": true
+ },
"highlight.js": {
"version": "9.13.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz",
@@ -4774,6 +5311,18 @@
"integrity": "sha512-Ba4+0M4YvIDUUsprMjhVTU1yN9F2/LJSAl69ZpzaLT4l4j5mwTS6jqqW9Ojvj6lKz/veqPzpJBqGbXspOb533A==",
"dev": true
},
+ "hsl-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz",
+ "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=",
+ "dev": true
+ },
+ "hsla-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
+ "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
+ "dev": true
+ },
"html-comment-regex": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz",
@@ -4820,19 +5369,57 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
- "icss-replace-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
- "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
- "dev": true
- },
"icss-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz",
- "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz",
+ "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==",
"dev": true,
"requires": {
- "postcss": "^6.0.1"
+ "postcss": "^7.0.14"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
}
},
"ieee754": {
@@ -4853,6 +5440,33 @@
"integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
"dev": true
},
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "dev": true,
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ },
+ "dependencies": {
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "dev": true,
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ }
+ }
+ },
"import-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
@@ -5032,6 +5646,20 @@
"ci-info": "^1.5.0"
}
},
+ "is-color-stop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz",
+ "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=",
+ "dev": true,
+ "requires": {
+ "css-color-names": "^0.0.4",
+ "hex-color-regex": "^1.1.0",
+ "hsl-regex": "^1.0.0",
+ "hsla-regex": "^1.0.0",
+ "rgb-regex": "^1.0.1",
+ "rgba-regex": "^1.0.0"
+ }
+ },
"is-data-descriptor": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
@@ -5138,6 +5766,12 @@
"kind-of": "^3.0.2"
}
},
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
"is-path-cwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
@@ -5216,15 +5850,6 @@
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
"dev": true
},
- "is-svg": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz",
- "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=",
- "dev": true,
- "requires": {
- "html-comment-regex": "^1.1.0"
- }
- },
"is-symbol": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
@@ -5252,6 +5877,12 @@
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -6257,6 +6888,16 @@
"integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==",
"dev": true
},
+ "last-call-webpack-plugin": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz",
+ "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.5",
+ "webpack-sources": "^1.1.0"
+ }
+ },
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
@@ -6352,12 +6993,6 @@
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
"dev": true
},
- "lodash.camelcase": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
- "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
- "dev": true
- },
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@@ -6479,12 +7114,6 @@
"object-visit": "^1.0.0"
}
},
- "math-expression-evaluator": {
- "version": "1.2.17",
- "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
- "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=",
- "dev": true
- },
"math-random": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
@@ -6501,6 +7130,12 @@
"inherits": "^2.0.1"
}
},
+ "mdn-data": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
+ "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
+ "dev": true
+ },
"mem": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
@@ -6700,6 +7335,61 @@
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"dev": true
},
+ "mini-css-extract-plugin": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz",
+ "integrity": "sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "normalize-url": "1.9.1",
+ "schema-utils": "^1.0.0",
+ "webpack-sources": "^1.1.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
@@ -6961,6 +7651,15 @@
}
}
},
+ "node-releases": {
+ "version": "1.1.26",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz",
+ "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ },
"node-sass": {
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz",
@@ -7094,6 +7793,15 @@
"set-blocking": "~2.0.0"
}
},
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
"num2fraction": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@@ -7206,6 +7914,18 @@
"isobject": "^3.0.1"
}
},
+ "object.values": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
+ "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.12.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3"
+ }
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -7242,6 +7962,110 @@
}
}
},
+ "optimize-css-assets-webpack-plugin": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz",
+ "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==",
+ "dev": true,
+ "requires": {
+ "cssnano": "^4.1.10",
+ "last-call-webpack-plugin": "^3.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "dev": true,
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "cssnano": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz",
+ "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "cssnano-preset-default": "^4.0.7",
+ "is-resolvable": "^1.0.0",
+ "postcss": "^7.0.0"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
"optionator": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
@@ -7553,1932 +8377,699 @@
"supports-color": "^5.4.0"
}
},
- "postcss-calc": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz",
- "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=",
+ "postcss-load-config": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz",
+ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
"dev": true,
"requires": {
- "postcss": "^5.0.2",
- "postcss-message-helpers": "^2.0.0",
- "reduce-css-calc": "^1.2.6"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
+ "cosmiconfig": "^2.1.0",
+ "object-assign": "^4.1.0",
+ "postcss-load-options": "^1.2.0",
+ "postcss-load-plugins": "^2.3.0"
}
},
- "postcss-colormin": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz",
- "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=",
- "dev": true,
- "requires": {
- "colormin": "^1.0.5",
- "postcss": "^5.0.13",
- "postcss-value-parser": "^3.2.3"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-convert-values": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz",
- "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.11",
- "postcss-value-parser": "^3.1.2"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-discard-comments": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz",
- "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.14"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-discard-duplicates": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz",
- "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.4"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-discard-empty": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz",
- "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.14"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-discard-overridden": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz",
- "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.16"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-discard-unused": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz",
- "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.14",
- "uniqs": "^2.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-filter-plugins": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz",
- "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==",
- "dev": true,
- "requires": {
- "postcss": "^5.0.4"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-load-config": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz",
- "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
- "dev": true,
- "requires": {
- "cosmiconfig": "^2.1.0",
- "object-assign": "^4.1.0",
- "postcss-load-options": "^1.2.0",
- "postcss-load-plugins": "^2.3.0"
- }
- },
- "postcss-load-options": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz",
- "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
- "dev": true,
- "requires": {
- "cosmiconfig": "^2.1.0",
- "object-assign": "^4.1.0"
- }
- },
- "postcss-load-plugins": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz",
- "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
- "dev": true,
- "requires": {
- "cosmiconfig": "^2.1.1",
- "object-assign": "^4.1.0"
- }
- },
- "postcss-loader": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.5.tgz",
- "integrity": "sha512-pV7kB5neJ0/1tZ8L1uGOBNTVBCSCXQoIsZMsrwvO8V2rKGa2tBl/f80GGVxow2jJnRJ2w1ocx693EKhZAb9Isg==",
- "dev": true,
- "requires": {
- "loader-utils": "^1.1.0",
- "postcss": "^6.0.0",
- "postcss-load-config": "^1.2.0",
- "schema-utils": "^0.4.0"
- }
- },
- "postcss-merge-idents": {
- "version": "2.1.7",
- "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz",
- "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=",
- "dev": true,
- "requires": {
- "has": "^1.0.1",
- "postcss": "^5.0.10",
- "postcss-value-parser": "^3.1.1"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-merge-longhand": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz",
- "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.4"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-merge-rules": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz",
- "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=",
- "dev": true,
- "requires": {
- "browserslist": "^1.5.2",
- "caniuse-api": "^1.5.2",
- "postcss": "^5.0.4",
- "postcss-selector-parser": "^2.2.2",
- "vendors": "^1.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "browserslist": {
- "version": "1.7.7",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
- "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
- "dev": true,
- "requires": {
- "caniuse-db": "^1.0.30000639",
- "electron-to-chromium": "^1.2.7"
- }
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-message-helpers": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz",
- "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=",
- "dev": true
- },
- "postcss-minify-font-values": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz",
- "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=",
- "dev": true,
- "requires": {
- "object-assign": "^4.0.1",
- "postcss": "^5.0.4",
- "postcss-value-parser": "^3.0.2"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
- }
- },
- "postcss-minify-gradients": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz",
- "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=",
- "dev": true,
- "requires": {
- "postcss": "^5.0.12",
- "postcss-value-parser": "^3.3.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- }
- }
- },
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
- "postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
- "dev": true,
- "requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
- "dev": true,
- "requires": {
- "has-flag": "^1.0.0"
- }
- }
+ "postcss-load-options": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz",
+ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^2.1.0",
+ "object-assign": "^4.1.0"
}
},
- "postcss-minify-params": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz",
- "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=",
+ "postcss-load-plugins": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz",
+ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^2.1.1",
+ "object-assign": "^4.1.0"
+ }
+ },
+ "postcss-loader": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.5.tgz",
+ "integrity": "sha512-pV7kB5neJ0/1tZ8L1uGOBNTVBCSCXQoIsZMsrwvO8V2rKGa2tBl/f80GGVxow2jJnRJ2w1ocx693EKhZAb9Isg==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "postcss": "^6.0.0",
+ "postcss-load-config": "^1.2.0",
+ "schema-utils": "^0.4.0"
+ }
+ },
+ "postcss-modules-extract-imports": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
+ "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==",
"dev": true,
"requires": {
- "alphanum-sort": "^1.0.1",
- "postcss": "^5.0.2",
- "postcss-value-parser": "^3.0.2",
- "uniqs": "^2.0.0"
+ "postcss": "^7.0.5"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-minify-selectors": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz",
- "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=",
+ "postcss-modules-local-by-default": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz",
+ "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==",
"dev": true,
"requires": {
- "alphanum-sort": "^1.0.2",
- "has": "^1.0.1",
- "postcss": "^5.0.14",
- "postcss-selector-parser": "^2.0.0"
+ "icss-utils": "^4.1.1",
+ "postcss": "^7.0.16",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "postcss-value-parser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz",
+ "integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==",
"dev": true
},
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-modules-extract-imports": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz",
- "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=",
- "dev": true,
- "requires": {
- "postcss": "^6.0.1"
- }
- },
- "postcss-modules-local-by-default": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz",
- "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=",
- "dev": true,
- "requires": {
- "css-selector-tokenizer": "^0.7.0",
- "postcss": "^6.0.1"
- }
- },
"postcss-modules-scope": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz",
- "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=",
- "dev": true,
- "requires": {
- "css-selector-tokenizer": "^0.7.0",
- "postcss": "^6.0.1"
- }
- },
- "postcss-modules-values": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz",
- "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=",
- "dev": true,
- "requires": {
- "icss-replace-symbols": "^1.1.0",
- "postcss": "^6.0.1"
- }
- },
- "postcss-normalize-charset": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz",
- "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz",
+ "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==",
"dev": true,
"requires": {
- "postcss": "^5.0.5"
+ "postcss": "^7.0.6",
+ "postcss-selector-parser": "^6.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-normalize-url": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz",
- "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=",
+ "postcss-modules-values": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz",
+ "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==",
"dev": true,
"requires": {
- "is-absolute-url": "^2.0.0",
- "normalize-url": "^1.4.0",
- "postcss": "^5.0.14",
- "postcss-value-parser": "^3.2.3"
+ "icss-utils": "^4.0.0",
+ "postcss": "^7.0.6"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-ordered-values": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz",
- "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=",
+ "postcss-normalize-display-values": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz",
+ "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==",
"dev": true,
"requires": {
- "postcss": "^5.0.4",
- "postcss-value-parser": "^3.0.1"
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-reduce-idents": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz",
- "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=",
+ "postcss-normalize-positions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz",
+ "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==",
"dev": true,
"requires": {
- "postcss": "^5.0.4",
- "postcss-value-parser": "^3.0.2"
+ "cssnano-util-get-arguments": "^4.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-reduce-initial": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz",
- "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=",
+ "postcss-normalize-repeat-style": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz",
+ "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==",
"dev": true,
"requires": {
- "postcss": "^5.0.4"
+ "cssnano-util-get-arguments": "^4.0.0",
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-reduce-transforms": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz",
- "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=",
+ "postcss-normalize-string": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz",
+ "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==",
"dev": true,
"requires": {
- "has": "^1.0.1",
- "postcss": "^5.0.8",
- "postcss-value-parser": "^3.0.1"
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-selector-parser": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz",
- "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=",
- "dev": true,
- "requires": {
- "flatten": "^1.0.2",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
- }
- },
- "postcss-svgo": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz",
- "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=",
+ "postcss-normalize-timing-functions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz",
+ "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==",
"dev": true,
"requires": {
- "is-svg": "^2.0.0",
- "postcss": "^5.0.14",
- "postcss-value-parser": "^3.2.3",
- "svgo": "^0.7.0"
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-unique-selectors": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz",
- "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=",
+ "postcss-normalize-unicode": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz",
+ "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==",
"dev": true,
"requires": {
- "alphanum-sort": "^1.0.1",
- "postcss": "^5.0.4",
- "uniqs": "^2.0.0"
+ "browserslist": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "browserslist": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
+ "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000984",
+ "electron-to-chromium": "^1.3.191",
+ "node-releases": "^1.1.25"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000985",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz",
+ "integrity": "sha512-1ngiwkgqAYPG0JSSUp3PUDGPKKY59EK7NrGGX+VOxaKCNzRbNc7uXMny+c3VJfZxtoK3wSImTvG9T9sXiTw2+w==",
"dev": true
},
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "electron-to-chromium": {
+ "version": "1.3.200",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz",
+ "integrity": "sha512-PUurrpyDA74MuAjJRD+79ss5BqJlU3mdArRbuu4wO/dt6jc3Ic/6BDmFJxkdwbfq39cHf/XKm2vW98XSvut9Dg==",
"dev": true
},
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
- "postcss-value-parser": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
- "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
- "dev": true
- },
- "postcss-zindex": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz",
- "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=",
+ "postcss-normalize-whitespace": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz",
+ "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==",
"dev": true,
"requires": {
- "has": "^1.0.1",
- "postcss": "^5.0.4",
- "uniqs": "^2.0.0"
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
},
"dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
}
}
},
- "has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
- "dev": true
- },
"postcss": {
- "version": "5.2.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
"dev": true,
"requires": {
- "chalk": "^1.1.3",
- "js-base64": "^2.1.9",
- "source-map": "^0.5.6",
- "supports-color": "^3.2.3"
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
}
},
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
"supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
- "has-flag": "^1.0.0"
+ "has-flag": "^3.0.0"
}
}
}
},
+ "postcss-selector-parser": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
+ "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^3.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
+ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
+ "dev": true
+ },
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -9765,42 +9356,6 @@
"strip-indent": "^1.0.1"
}
},
- "reduce-css-calc": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
- "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
- "dev": true,
- "requires": {
- "balanced-match": "^0.4.2",
- "math-expression-evaluator": "^1.2.14",
- "reduce-function-call": "^1.0.1"
- },
- "dependencies": {
- "balanced-match": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
- "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=",
- "dev": true
- }
- }
- },
- "reduce-function-call": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz",
- "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=",
- "dev": true,
- "requires": {
- "balanced-match": "^0.4.2"
- },
- "dependencies": {
- "balanced-match": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
- "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=",
- "dev": true
- }
- }
- },
"reduce-reducers": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz",
@@ -10071,6 +9626,18 @@
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
"dev": true
},
+ "rgb-regex": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
+ "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=",
+ "dev": true
+ },
+ "rgba-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
+ "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
+ "dev": true
+ },
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
@@ -10366,16 +9933,17 @@
}
},
"sass-loader": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.0.3.tgz",
- "integrity": "sha512-iaSFtQcGo4SSgDw5Aes5p4VTrA5jCGSA7sGmhPIcOloBlgI1VktM2MUrk2IHHjbNagckXlPz+HWq1vAAPrcYxA==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz",
+ "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==",
"dev": true,
"requires": {
"clone-deep": "^2.0.1",
"loader-utils": "^1.0.1",
"lodash.tail": "^4.1.1",
"neo-async": "^2.5.0",
- "pify": "^3.0.0"
+ "pify": "^3.0.0",
+ "semver": "^5.5.0"
}
},
"sax": {
@@ -10566,6 +10134,23 @@
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true
},
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.3.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "dev": true
+ }
+ }
+ },
"sisteransi": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz",
@@ -10825,6 +10410,12 @@
"safe-buffer": "^5.1.1"
}
},
+ "stable": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
+ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
+ "dev": true
+ },
"stack-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz",
@@ -10994,6 +10585,95 @@
"schema-utils": "^0.4.5"
}
},
+ "stylehacks": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
+ "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
+ "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000984",
+ "electron-to-chromium": "^1.3.191",
+ "node-releases": "^1.1.25"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000985",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz",
+ "integrity": "sha512-1ngiwkgqAYPG0JSSUp3PUDGPKKY59EK7NrGGX+VOxaKCNzRbNc7uXMny+c3VJfZxtoK3wSImTvG9T9sXiTw2+w==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.3.200",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz",
+ "integrity": "sha512-PUurrpyDA74MuAjJRD+79ss5BqJlU3mdArRbuu4wO/dt6jc3Ic/6BDmFJxkdwbfq39cHf/XKm2vW98XSvut9Dg==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz",
+ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.1",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
@@ -11003,21 +10683,6 @@
"has-flag": "^3.0.0"
}
},
- "svgo": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz",
- "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=",
- "dev": true,
- "requires": {
- "coa": "~1.0.1",
- "colors": "~1.1.2",
- "csso": "~2.3.1",
- "js-yaml": "~3.7.0",
- "mkdirp": "~0.5.1",
- "sax": "~1.2.1",
- "whet.extend": "~0.9.9"
- }
- },
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
@@ -11060,6 +10725,362 @@
"inherits": "2"
}
},
+ "terser": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz",
+ "integrity": "sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==",
+ "dev": true,
+ "requires": {
+ "commander": "^2.20.0",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.12"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.20.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+ "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.12",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
+ "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ }
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz",
+ "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==",
+ "dev": true,
+ "requires": {
+ "cacache": "^11.3.2",
+ "find-cache-dir": "^2.0.0",
+ "is-wsl": "^1.1.0",
+ "loader-utils": "^1.2.3",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^1.7.0",
+ "source-map": "^0.6.1",
+ "terser": "^4.0.0",
+ "webpack-sources": "^1.3.0",
+ "worker-farm": "^1.7.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+ "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+ "dev": true
+ },
+ "cacache": {
+ "version": "11.3.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+ "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "chownr": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz",
+ "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
+ "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+ "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "semver": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "dev": true
+ },
+ "serialize-javascript": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz",
+ "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
+ "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ }
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+ "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+ "dev": true,
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "dev": true
+ }
+ }
+ },
"test-exclude": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz",
@@ -11271,6 +11292,12 @@
"setimmediate": "^1.0.4"
}
},
+ "timsort": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
+ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
+ "dev": true
+ },
"tiny-emitter": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz",
@@ -11542,6 +11569,12 @@
"imurmurhash": "^0.1.4"
}
},
+ "unquote": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
+ "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=",
+ "dev": true
+ },
"unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -11968,12 +12001,6 @@
"webidl-conversions": "^4.0.2"
}
},
- "whet.extend": {
- "version": "0.9.9",
- "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",
- "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=",
- "dev": true
- },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
diff --git a/apps/block_scout_web/assets/package.json b/apps/block_scout_web/assets/package.json
index 18d4d0e592..5a615bee33 100644
--- a/apps/block_scout_web/assets/package.json
+++ b/apps/block_scout_web/assets/package.json
@@ -20,12 +20,13 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.1.0-4",
- "highlight.js": "^9.13.1",
- "highlightjs-solidity": "^1.0.6",
+ "awesomplete": "1.1.2",
"bignumber.js": "^7.2.1",
"bootstrap": "^4.1.3",
"chart.js": "^2.7.2",
"clipboard": "^2.0.1",
+ "highlight.js": "^9.13.1",
+ "highlightjs-solidity": "^1.0.6",
"humps": "^2.0.1",
"jquery": "^3.3.1",
"lodash": "^4.17.11",
@@ -47,20 +48,22 @@
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"copy-webpack-plugin": "^4.5.1",
- "css-loader": "^0.28.11",
+ "css-loader": "^3.1.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^11.0.0-beta.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-standard": "^3.0.1",
- "extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^1.1.11",
"jest": "^23.2.0",
+ "mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.9.3",
+ "optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^2.1.4",
- "sass-loader": "^7.0.1",
+ "sass-loader": "^7.1.0",
"style-loader": "^0.21.0",
+ "terser-webpack-plugin": "^1.3.0",
"webpack": "^4.6.0",
"webpack-cli": "^3.0.8"
},
diff --git a/apps/block_scout_web/assets/webpack.config.js b/apps/block_scout_web/assets/webpack.config.js
index 08a2f410e7..05ac405ab0 100644
--- a/apps/block_scout_web/assets/webpack.config.js
+++ b/apps/block_scout_web/assets/webpack.config.js
@@ -1,7 +1,9 @@
const path = require('path');
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const TerserJSPlugin = require('terser-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
-const { ContextReplacementPlugin } = require('webpack')
+const { ContextReplacementPlugin } = require('webpack');
const glob = require("glob");
function transpileViewScript(file) {
@@ -25,6 +27,46 @@ function transpileViewScript(file) {
}
};
+const jsOptimizationParams = {
+ cache: true,
+ parallel: true,
+ sourceMap: true,
+}
+
+const awesompleteJs = {
+ entry: {
+ awesomplete: './js/lib/awesomplete.js',
+ 'awesomplete-util': './js/lib/awesomplete-util.js',
+ },
+ output: {
+ filename: '[name].min.js',
+ path: path.resolve(__dirname, '../priv/static/js')
+ },
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
+ loader: "css-loader",
+ }
+ ],
+ },
+ ],
+ },
+ optimization: {
+ minimizer: [
+ new TerserJSPlugin(jsOptimizationParams),
+ ],
+ },
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '../css/awesomplete.css'
+ }),
+ ]
+}
+
const appJs =
{
entry: './js/app.js',
@@ -32,6 +74,9 @@ const appJs =
filename: 'app.js',
path: path.resolve(__dirname, '../priv/static/js')
},
+ optimization: {
+ minimizer: [new TerserJSPlugin(jsOptimizationParams), new OptimizeCSSAssetsPlugin({})],
+ },
module: {
rules: [
{
@@ -43,8 +88,9 @@ const appJs =
},
{
test: /\.scss$/,
- use: ExtractTextPlugin.extract({
- use: [{
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
loader: "css-loader"
}, {
loader: "postcss-loader"
@@ -57,9 +103,8 @@ const appJs =
'node_modules/@fortawesome/fontawesome-free/scss'
]
}
- }],
- fallback: 'style-loader'
- })
+ }
+ ]
}, {
test: /\.(svg|ttf|eot|woff|woff2)$/,
use: {
@@ -74,7 +119,9 @@ const appJs =
]
},
plugins: [
- new ExtractTextPlugin('../css/app.css'),
+ new MiniCssExtractPlugin({
+ filename: '../css/app.css'
+ }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
new ContextReplacementPlugin(/moment[\/\\]locale$/, /en/)
]
@@ -82,4 +129,4 @@ const appJs =
const viewScripts = glob.sync('./js/view_specific/**/*.js').map(transpileViewScript);
-module.exports = viewScripts.concat(appJs);
+module.exports = viewScripts.concat(appJs, awesompleteJs);
diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs
index 836a21ba02..9dae076638 100644
--- a/apps/block_scout_web/config/config.exs
+++ b/apps/block_scout_web/config/config.exs
@@ -58,8 +58,7 @@ config :block_scout_web, BlockScoutWeb.SocialMedia,
config :ex_cldr,
default_locale: "en",
- locales: ["en"],
- gettext: BlockScoutWeb.Gettext
+ default_backend: BlockScoutWeb.Cldr
config :logger, :block_scout_web,
# keep synced with `config/config.exs`
diff --git a/apps/block_scout_web/lib/block_scout_web/chain.ex b/apps/block_scout_web/lib/block_scout_web/chain.ex
index 9e82c30023..b1a3c3ec19 100644
--- a/apps/block_scout_web/lib/block_scout_web/chain.ex
+++ b/apps/block_scout_web/lib/block_scout_web/chain.ex
@@ -124,18 +124,20 @@ defmodule BlockScoutWeb.Chain do
end
def paging_options(%{"block_number" => block_number_string}) do
- with {block_number, ""} <- Integer.parse(block_number_string) do
- [paging_options: %{@default_paging_options | key: {block_number}}]
- else
+ case Integer.parse(block_number_string) do
+ {block_number, ""} ->
+ [paging_options: %{@default_paging_options | key: {block_number}}]
+
_ ->
[paging_options: @default_paging_options]
end
end
def paging_options(%{"index" => index_string}) when is_binary(index_string) do
- with {index, ""} <- Integer.parse(index_string) do
- [paging_options: %{@default_paging_options | key: {index}}]
- else
+ case Integer.parse(index_string) do
+ {index, ""} ->
+ [paging_options: %{@default_paging_options | key: {index}}]
+
_ ->
[paging_options: @default_paging_options]
end
@@ -174,10 +176,12 @@ defmodule BlockScoutWeb.Chain do
def split_list_by_page(list_plus_one), do: Enum.split(list_plus_one, @page_size)
defp address_from_param(param) do
- with {:ok, hash} <- string_to_address_hash(param) do
- find_or_insert_address_from_hash(hash)
- else
- :error -> {:error, :not_found}
+ case string_to_address_hash(param) do
+ {:ok, hash} ->
+ find_or_insert_address_from_hash(hash)
+
+ :error ->
+ {:error, :not_found}
end
end
@@ -246,18 +250,22 @@ defmodule BlockScoutWeb.Chain do
end
defp transaction_from_param(param) do
- with {:ok, hash} <- string_to_transaction_hash(param) do
- hash_to_transaction(hash)
- else
- :error -> {:error, :not_found}
+ case string_to_transaction_hash(param) do
+ {:ok, hash} ->
+ hash_to_transaction(hash)
+
+ :error ->
+ {:error, :not_found}
end
end
defp hash_string_to_block(hash_string) do
- with {:ok, hash} <- string_to_block_hash(hash_string) do
- hash_to_block(hash)
- else
- :error -> {:error, :not_found}
+ case string_to_block_hash(hash_string) do
+ {:ok, hash} ->
+ hash_to_block(hash)
+
+ :error ->
+ {:error, :not_found}
end
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
index 4009d4f461..c13692f7ea 100644
--- a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
+++ b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
@@ -73,7 +73,7 @@ defmodule BlockScoutWeb.AddressChannel do
def handle_out("count", %{count: count}, socket) do
Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale)
- push(socket, "count", %{count: Cldr.Number.to_string!(count, format: "#,###")})
+ push(socket, "count", %{count: BlockScoutWeb.Cldr.Number.to_string!(count, format: "#,###")})
{:noreply, socket}
end
diff --git a/apps/block_scout_web/lib/block_scout_web/cldr.ex b/apps/block_scout_web/lib/block_scout_web/cldr.ex
new file mode 100644
index 0000000000..7b9d77d7e2
--- /dev/null
+++ b/apps/block_scout_web/lib/block_scout_web/cldr.ex
@@ -0,0 +1,12 @@
+defmodule BlockScoutWeb.Cldr do
+ @moduledoc """
+ Cldr global configuration.
+ """
+
+ use Cldr,
+ default_locale: "en",
+ locales: ["en"],
+ gettext: BlockScoutWeb.Gettext,
+ generate_docs: false,
+ providers: [Cldr.Number, Cldr.Unit]
+end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex
index 33a01959c9..8b39de91a7 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex
@@ -16,7 +16,7 @@ defmodule BlockScoutWeb.AddressCoinBalanceController 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),
- {:ok, address} <- Chain.hash_to_address(address_hash, [], false) do
+ :ok <- Chain.check_address_exists(address_hash) do
full_options = paging_options(params)
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(
conn,
:index,
- address,
+ address_hash,
Map.delete(next_page_params, "type")
)
end
@@ -52,7 +52,7 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
:error ->
unprocessable_entity(conn)
- {:error, :not_found} ->
+ :not_found ->
not_found(conn)
end
end
@@ -68,6 +68,12 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
validation_count: validation_count(address_hash),
current_path: current_path(conn)
)
+ else
+ :error ->
+ unprocessable_entity(conn)
+
+ {:error, :not_found} ->
+ not_found(conn)
end
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex
index bc4df8c4be..5db900b12b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex
@@ -8,8 +8,18 @@ defmodule BlockScoutWeb.AddressContractController do
alias Indexer.Fetcher.CoinBalanceOnDemand
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),
- {:ok, address} <- Chain.find_contract_address(address_hash) do
+ {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true) do
render(
conn,
"index.html",
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
index e349ecd9ef..d3ea4e5303 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
@@ -16,7 +16,7 @@ defmodule BlockScoutWeb.AddressLogsController 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),
- {: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))
{results, next_page} = split_list_by_page(logs_plus_one)
@@ -26,7 +26,7 @@ defmodule BlockScoutWeb.AddressLogsController do
nil
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
items =
@@ -74,7 +74,7 @@ defmodule BlockScoutWeb.AddressLogsController 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),
- {:ok, address} <- Chain.hash_to_address(address_hash, [], false) do
+ :ok <- Chain.check_address_exists(address_hash) do
topic = String.trim(topic)
formatted_topic = if String.starts_with?(topic, "0x"), do: topic, else: "0x" <> topic
@@ -89,7 +89,7 @@ defmodule BlockScoutWeb.AddressLogsController do
nil
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
items =
@@ -115,4 +115,6 @@ defmodule BlockScoutWeb.AddressLogsController do
not_found(conn)
end
end
+
+ def search_logs(conn, _), do: not_found(conn)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
index d57aa30807..0849689dce 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
@@ -15,8 +15,18 @@ defmodule BlockScoutWeb.AddressReadContractController do
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
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),
- {:ok, address} <- Chain.find_contract_address(address_hash) do
+ {:ok, address} <- Chain.find_contract_address(address_hash, address_options, true) do
render(
conn,
"index.html",
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
index f6d9b8a30f..f30c3cb0cd 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
@@ -83,7 +83,13 @@ defmodule BlockScoutWeb.AddressTransactionController do
unprocessable_entity(conn)
{:error, :not_found} ->
- not_found(conn)
+ case Chain.Hash.Address.validate(address_hash_string) do
+ {:ok, _} ->
+ json(conn, %{items: [], next_page_path: ""})
+
+ _ ->
+ not_found(conn)
+ end
end
end
@@ -106,11 +112,30 @@ defmodule BlockScoutWeb.AddressTransactionController do
unprocessable_entity(conn)
{:error, :not_found} ->
- not_found(conn)
+ {:ok, address_hash} = Chain.string_to_address_hash(address_hash_string)
+ address = %Chain.Address{hash: address_hash, smart_contract: nil, token: nil}
+
+ case Chain.Hash.Address.validate(address_hash_string) do
+ {:ok, _} ->
+ render(
+ conn,
+ "index.html",
+ address: address,
+ coin_balance_status: nil,
+ exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
+ filter: params["filter"],
+ transaction_count: 0,
+ validation_count: 0,
+ current_path: current_path(conn)
+ )
+
+ _ ->
+ not_found(conn)
+ end
end
end
- def token_transfers_csv(conn, %{"address_id" => address_hash_string}) do
+ def token_transfers_csv(conn, %{"address_id" => address_hash_string}) when is_binary(address_hash_string) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
address
@@ -130,6 +155,8 @@ defmodule BlockScoutWeb.AddressTransactionController do
end
end
+ def token_transfers_csv(conn, _), do: not_found(conn)
+
def transactions_csv(conn, %{"address_id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
@@ -149,4 +176,6 @@ defmodule BlockScoutWeb.AddressTransactionController do
not_found(conn)
end
end
+
+ def transactions_csv(conn, _), do: not_found(conn)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
index 91569a96da..835e19bf3e 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
@@ -8,9 +8,8 @@ defmodule BlockScoutWeb.API.RPC.BlockController do
def getblockreward(conn, params) do
with {:block_param, {:ok, unsafe_block_number}} <- {:block_param, Map.fetch(params, "blockno")},
{: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, block_options) do
- reward = Chain.block_reward(block)
+ {:ok, block} <- Chain.number_to_block(block_number) do
+ reward = Chain.block_reward(block_number)
render(conn, :block_reward, block: block, reward: reward)
else
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/eth_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/eth_controller.ex
index 028084e73f..26ffd5e47f 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/eth_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/eth_controller.ex
@@ -1,44 +1,10 @@
defmodule BlockScoutWeb.API.RPC.EthController do
use BlockScoutWeb, :controller
- alias Ecto.Type, as: EctoType
- alias Explorer.{Chain, Repo}
- alias Explorer.Chain.{Block, Data, Hash, Hash.Address, Wei}
- alias Explorer.Etherscan.Logs
-
- @methods %{
- "eth_getBalance" => %{
- action: :eth_get_balance,
- notes: """
- the `earliest` parameter will not work as expected currently, because genesis block balances
- are not currently imported
- """,
- example: """
- {"id": 0, "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["0x0000000000000000000000000000000000000007", "2"]}
- """
- },
- "eth_getLogs" => %{
- action: :eth_get_logs,
- notes: """
- Will never return more than 1000 log entries.
- """,
- example: """
- {"id": 0, "jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"address": "0x0000000000000000000000000000000000000026","topics": ["0x01"]}]}
- """
- }
- }
-
- @index_to_word %{
- 0 => "first",
- 1 => "second",
- 2 => "third",
- 3 => "fourth"
- }
-
- def methods, do: @methods
+ alias Explorer.EthRPC
def eth_request(%{body_params: %{"_json" => requests}} = conn, _) when is_list(requests) do
- responses = responses(requests)
+ responses = EthRPC.responses(requests)
conn
|> put_status(200)
@@ -46,7 +12,7 @@ defmodule BlockScoutWeb.API.RPC.EthController do
end
def eth_request(%{body_params: %{"_json" => request}} = conn, _) do
- [response] = responses([request])
+ [response] = EthRPC.responses([request])
conn
|> put_status(200)
@@ -65,297 +31,10 @@ defmodule BlockScoutWeb.API.RPC.EthController do
_ -> request
end
- [response] = responses([decoded_request])
+ [response] = EthRPC.responses([decoded_request])
conn
|> put_status(200)
|> render("response.json", %{response: response})
end
-
- def eth_get_balance(address_param, block_param \\ nil) do
- with {:address, {:ok, address}} <- {:address, Chain.string_to_address_hash(address_param)},
- {:block, {:ok, block}} <- {:block, block_param(block_param)},
- {:balance, {:ok, balance}} <- {:balance, Chain.get_balance_as_of_block(address, block)} do
- {:ok, Wei.hex_format(balance)}
- else
- {:address, :error} ->
- {:error, "Query parameter 'address' is invalid"}
-
- {:block, :error} ->
- {:error, "Query parameter 'block' is invalid"}
-
- {:balance, {:error, :not_found}} ->
- {:error, "Balance not found"}
- end
- end
-
- def eth_get_logs(filter_options) do
- with {:ok, address_or_topic_params} <- address_or_topic_params(filter_options),
- {:ok, from_block_param, to_block_param} <- logs_blocks_filter(filter_options),
- {:ok, from_block} <- cast_block(from_block_param),
- {:ok, to_block} <- cast_block(to_block_param) do
- filter =
- address_or_topic_params
- |> Map.put(:from_block, from_block)
- |> Map.put(:to_block, to_block)
- |> Map.put(:allow_non_consensus, true)
-
- {:ok, filter |> Logs.list_logs() |> Enum.map(&render_log/1)}
- else
- {:error, message} when is_bitstring(message) ->
- {:error, message}
-
- {:error, :empty} ->
- {:ok, []}
-
- _ ->
- {:error, "Something went wrong."}
- end
- end
-
- defp render_log(log) do
- topics =
- Enum.reject(
- [log.first_topic, log.second_topic, log.third_topic, log.fourth_topic],
- &is_nil/1
- )
-
- %{
- "address" => to_string(log.address_hash),
- "blockHash" => to_string(log.block_hash),
- "blockNumber" => Integer.to_string(log.block_number, 16),
- "data" => to_string(log.data),
- "logIndex" => Integer.to_string(log.index, 16),
- "removed" => log.block_consensus == false,
- "topics" => topics,
- "transactionHash" => to_string(log.transaction_hash),
- "transactionIndex" => log.transaction_index,
- "transactionLogIndex" => log.index,
- "type" => "mined"
- }
- end
-
- defp cast_block("0x" <> hexadecimal_digits = input) do
- case Integer.parse(hexadecimal_digits, 16) do
- {integer, ""} -> {:ok, integer}
- _ -> {:error, input <> " is not a valid block number"}
- end
- end
-
- defp cast_block(integer) when is_integer(integer), do: {:ok, integer}
- defp cast_block(_), do: {:error, "invalid block number"}
-
- defp address_or_topic_params(filter_options) do
- address_param = Map.get(filter_options, "address")
- topics_param = Map.get(filter_options, "topics")
-
- with {:ok, address} <- validate_address(address_param),
- {:ok, topics} <- validate_topics(topics_param) do
- address_and_topics(address, topics)
- end
- end
-
- defp address_and_topics(nil, nil), do: {:error, "Must supply one of address and topics"}
- defp address_and_topics(address, nil), do: {:ok, %{address_hash: address}}
- defp address_and_topics(nil, topics), do: {:ok, topics}
- defp address_and_topics(address, topics), do: {:ok, Map.put(topics, :address_hash, address)}
-
- defp validate_address(nil), do: {:ok, nil}
-
- defp validate_address(address) do
- case Address.cast(address) do
- {:ok, address} -> {:ok, address}
- :error -> {:error, "invalid address"}
- end
- end
-
- defp validate_topics(nil), do: {:ok, nil}
- defp validate_topics([]), do: []
-
- defp validate_topics(topics) when is_list(topics) do
- topics
- |> Stream.with_index()
- |> Enum.reduce({:ok, %{}}, fn {topic, index}, {:ok, acc} ->
- case cast_topics(topic) do
- {:ok, data} ->
- with_filter = Map.put(acc, String.to_existing_atom("#{@index_to_word[index]}_topic"), data)
-
- {:ok, add_operator(with_filter, index)}
-
- :error ->
- {:error, "invalid topics"}
- end
- end)
- end
-
- defp add_operator(filters, 0), do: filters
-
- defp add_operator(filters, index) do
- Map.put(filters, String.to_existing_atom("topic#{index - 1}_#{index}_opr"), "and")
- end
-
- defp cast_topics(topics) when is_list(topics) do
- case EctoType.cast({:array, Data}, topics) do
- {:ok, data} -> {:ok, Enum.map(data, &to_string/1)}
- :error -> :error
- end
- end
-
- defp cast_topics(topic) do
- case Data.cast(topic) do
- {:ok, data} -> {:ok, to_string(data)}
- :error -> :error
- end
- end
-
- defp responses(requests) do
- Enum.map(requests, fn request ->
- with {:id, {:ok, id}} <- {:id, Map.fetch(request, "id")},
- {:request, {:ok, result}} <- {:request, do_eth_request(request)} do
- format_success(result, id)
- else
- {:id, :error} -> format_error("id is a required field", 0)
- {:request, {:error, message}} -> format_error(message, Map.get(request, "id"))
- end
- end)
- end
-
- defp logs_blocks_filter(filter_options) do
- with {:filter, %{"blockHash" => block_hash_param}} <- {:filter, filter_options},
- {:block_hash, {:ok, block_hash}} <- {:block_hash, Hash.Full.cast(block_hash_param)},
- {:block, %{number: number}} <- {:block, Repo.get(Block, block_hash)} do
- {:ok, number, number}
- else
- {:filter, filters} ->
- from_block = Map.get(filters, "fromBlock", "latest")
- to_block = Map.get(filters, "toBlock", "latest")
-
- max_block_number =
- if from_block == "latest" || to_block == "latest" do
- max_consensus_block_number()
- end
-
- pending_block_number =
- if from_block == "pending" || to_block == "pending" do
- max_non_consensus_block_number(max_block_number)
- end
-
- if is_nil(pending_block_number) && from_block == "pending" && to_block == "pending" do
- {:error, :empty}
- else
- to_block_numbers(from_block, to_block, max_block_number, pending_block_number)
- end
-
- {:block, _} ->
- {:error, "Invalid Block Hash"}
-
- {:block_hash, _} ->
- {:error, "Invalid Block Hash"}
- end
- end
-
- defp to_block_numbers(from_block, to_block, max_block_number, pending_block_number) do
- actual_pending_block_number = pending_block_number || max_block_number
-
- with {:ok, from} <-
- to_block_number(from_block, max_block_number, actual_pending_block_number),
- {:ok, to} <- to_block_number(to_block, max_block_number, actual_pending_block_number) do
- {:ok, from, to}
- end
- end
-
- defp to_block_number(integer, _, _) when is_integer(integer), do: {:ok, integer}
- defp to_block_number("latest", max_block_number, _), do: {:ok, max_block_number || 0}
- defp to_block_number("earliest", _, _), do: {:ok, 0}
- defp to_block_number("pending", max_block_number, nil), do: {:ok, max_block_number || 0}
- defp to_block_number("pending", _, pending), do: {:ok, pending}
-
- defp to_block_number("0x" <> number, _, _) do
- case Integer.parse(number, 16) do
- {integer, ""} -> {:ok, integer}
- _ -> {:error, "invalid block number"}
- end
- end
-
- defp to_block_number(number, _, _) when is_bitstring(number) do
- case Integer.parse(number, 16) do
- {integer, ""} -> {:ok, integer}
- _ -> {:error, "invalid block number"}
- end
- end
-
- defp to_block_number(_, _, _), do: {:error, "invalid block number"}
-
- defp max_non_consensus_block_number(max) do
- case Chain.max_non_consensus_block_number(max) do
- {:ok, number} -> number
- _ -> nil
- end
- end
-
- defp max_consensus_block_number do
- case Chain.max_consensus_block_number() do
- {:ok, number} -> number
- _ -> nil
- end
- end
-
- defp format_success(result, id) do
- %{result: result, id: id}
- end
-
- defp format_error(message, id) do
- %{error: message, id: id}
- end
-
- defp do_eth_request(%{"jsonrpc" => rpc_version}) when rpc_version != "2.0" do
- {:error, "invalid rpc version"}
- end
-
- defp do_eth_request(%{"jsonrpc" => "2.0", "method" => method, "params" => params})
- when is_list(params) do
- with {:ok, action} <- get_action(method),
- {:correct_arity, true} <-
- {:correct_arity, :erlang.function_exported(__MODULE__, action, Enum.count(params))} do
- apply(__MODULE__, action, params)
- else
- {:correct_arity, _} ->
- {:error, "Incorrect number of params."}
-
- _ ->
- {:error, "Action not found."}
- end
- end
-
- defp do_eth_request(%{"params" => _params, "method" => _}) do
- {:error, "Invalid params. Params must be a list."}
- end
-
- defp do_eth_request(_) do
- {:error, "Method, params, and jsonrpc, are all required parameters."}
- end
-
- defp get_action(action) do
- case Map.get(@methods, action) do
- %{action: action} ->
- {:ok, action}
-
- _ ->
- :error
- end
- end
-
- defp block_param("latest"), do: {:ok, :latest}
- defp block_param("earliest"), do: {:ok, :earliest}
- defp block_param("pending"), do: {:ok, :pending}
-
- defp block_param(string_integer) when is_bitstring(string_integer) do
- case Integer.parse(string_integer) do
- {integer, ""} -> {:ok, integer}
- _ -> :error
- end
- end
-
- defp block_param(nil), do: {:ok, :latest}
- defp block_param(_), do: :error
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
index 344dbe1037..565ea4b6a5 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
@@ -10,7 +10,7 @@ defmodule BlockScoutWeb.API.RPC.TransactionController do
{:format, {:ok, transaction_hash}} <- to_transaction_hash(txhash_param),
{:transaction, {:ok, transaction}} <- transaction_from_hash(transaction_hash),
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)
render(conn, :gettxinfo, %{
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller.ex
index 1eec849380..7b783b9761 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller.ex
@@ -7,8 +7,9 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
def create(conn, params) do
if auth_token(conn) == actual_token() do
with {:ok, hash} <- validate_address_hash(params["address_hash"]),
- :ok <- smart_contract_exists?(hash),
- :ok <- decompiled_contract_exists?(params["address_hash"], params["decompiler_version"]) do
+ :ok <- Chain.check_address_exists(hash),
+ {:contract, :not_found} <-
+ {:contract, Chain.check_decompiled_contract_exists(params["address_hash"], params["decompiler_version"])} do
case Chain.create_decompiled_smart_contract(params) do
{:ok, decompiled_smart_contract} ->
send_resp(conn, :created, Jason.encode!(decompiled_smart_contract))
@@ -29,7 +30,7 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
:not_found ->
send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"}))
- :contract_exists ->
+ {:contract, :ok} ->
send_resp(
conn,
:unprocessable_entity,
@@ -41,13 +42,6 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
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
case Address.cast(address_hash) do
{:ok, hash} -> {:ok, hash}
@@ -55,13 +49,6 @@ defmodule BlockScoutWeb.API.V1.DecompiledSmartContractController do
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
case get_req_header(conn, "auth_token") do
[token] -> token
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
index 957dc797be..1e65fa75ba 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
@@ -4,19 +4,22 @@ defmodule BlockScoutWeb.API.V1.HealthController do
alias Explorer.Chain
def health(conn, _) do
- with {:ok, number, timestamp} <- Chain.last_block_status() do
- send_resp(conn, :ok, result(number, timestamp))
+ with {:ok, number, timestamp} <- Chain.last_db_block_status(),
+ {:ok, cache_number, cache_timestamp} <- Chain.last_cache_block_status() do
+ send_resp(conn, :ok, result(number, timestamp, cache_number, cache_timestamp))
else
status -> send_resp(conn, :internal_server_error, error(status))
end
end
- def result(number, timestamp) do
+ def result(number, timestamp, cache_number, cache_timestamp) do
%{
"healthy" => true,
"data" => %{
"latest_block_number" => to_string(number),
- "latest_block_inserted_at" => to_string(timestamp)
+ "latest_block_inserted_at" => to_string(timestamp),
+ "cache_latest_block_number" => to_string(cache_number),
+ "cache_latest_block_inserted_at" => to_string(cache_timestamp)
}
}
|> Jason.encode!()
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex
index 50334a1a45..8b3d3d71eb 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/verified_smart_contract_controller.ex
@@ -7,8 +7,8 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
def create(conn, params) do
with {:ok, hash} <- validate_address_hash(params["address_hash"]),
- :ok <- smart_contract_exists?(hash),
- :ok <- verified_smart_contract_exists?(hash) do
+ :ok <- Chain.check_address_exists(hash),
+ {:contract, :not_found} <- {:contract, Chain.check_verified_smart_contract_exists(hash)} do
external_libraries = fetch_external_libraries(params)
case Publisher.publish(hash, params, external_libraries) do
@@ -31,7 +31,7 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
:not_found ->
send_resp(conn, :unprocessable_entity, encode(%{error: "address is not found"}))
- :contract_exists ->
+ {:contract, :ok} ->
send_resp(
conn,
:unprocessable_entity,
@@ -40,13 +40,6 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
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
case Address.cast(address_hash) do
{:ok, hash} -> {:ok, hash}
@@ -54,14 +47,6 @@ defmodule BlockScoutWeb.API.V1.VerifiedSmartContractController do
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
Jason.encode!(data)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api_docs_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api_docs_controller.ex
index 9309884d5c..4a658c409e 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api_docs_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api_docs_controller.ex
@@ -1,8 +1,8 @@
defmodule BlockScoutWeb.APIDocsController do
use BlockScoutWeb, :controller
- alias BlockScoutWeb.API.RPC.EthController
alias BlockScoutWeb.Etherscan
+ alias Explorer.EthRPC
def index(conn, _params) do
conn
@@ -12,7 +12,7 @@ defmodule BlockScoutWeb.APIDocsController do
def eth_rpc(conn, _params) do
conn
- |> assign(:documentation, EthController.methods())
+ |> assign(:documentation, EthRPC.methods())
|> render("eth_rpc.html")
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
index 15b06f1edd..dd362cd065 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
@@ -11,57 +11,57 @@ defmodule BlockScoutWeb.BlockTransactionController do
alias Phoenix.View
def index(conn, %{"block_hash_or_number" => formatted_block_hash_or_number, "type" => "JSON"} = params) do
- with {:ok, block} <-
- param_block_hash_or_number_to_block(formatted_block_hash_or_number, []) do
- full_options =
- Keyword.merge(
- [
- necessity_by_association: %{
- :block => :optional,
- [created_contract_address: :names] => :optional,
- [from_address: :names] => :required,
- [to_address: :names] => :optional
- }
- ],
- paging_options(params)
- )
-
- transactions_plus_one = Chain.block_to_transactions(block, full_options)
-
- {transactions, next_page} = split_list_by_page(transactions_plus_one)
-
- next_page_path =
- case next_page_params(next_page, transactions, params) do
- nil ->
- nil
+ case param_block_hash_or_number_to_block(formatted_block_hash_or_number, []) do
+ {:ok, block} ->
+ full_options =
+ Keyword.merge(
+ [
+ necessity_by_association: %{
+ :block => :optional,
+ [created_contract_address: :names] => :optional,
+ [from_address: :names] => :required,
+ [to_address: :names] => :optional
+ }
+ ],
+ paging_options(params)
+ )
- next_page_params ->
- block_transaction_path(
- conn,
- :index,
- block,
- Map.delete(next_page_params, "type")
+ transactions_plus_one = Chain.block_to_transactions(block.hash, full_options)
+
+ {transactions, next_page} = split_list_by_page(transactions_plus_one)
+
+ next_page_path =
+ case next_page_params(next_page, transactions, params) do
+ nil ->
+ nil
+
+ next_page_params ->
+ block_transaction_path(
+ conn,
+ :index,
+ block,
+ Map.delete(next_page_params, "type")
+ )
+ end
+
+ items =
+ transactions
+ |> Enum.map(fn transaction ->
+ View.render_to_string(
+ TransactionView,
+ "_tile.html",
+ transaction: transaction
)
- end
-
- items =
- transactions
- |> Enum.map(fn transaction ->
- View.render_to_string(
- TransactionView,
- "_tile.html",
- transaction: transaction
- )
- end)
-
- json(
- conn,
- %{
- items: items,
- next_page_path: next_page_path
- }
- )
- else
+ end)
+
+ json(
+ conn,
+ %{
+ items: items,
+ next_page_path: next_page_path
+ }
+ )
+
{:error, {:invalid, :hash}} ->
not_found(conn)
@@ -80,25 +80,25 @@ defmodule BlockScoutWeb.BlockTransactionController do
end
def index(conn, %{"block_hash_or_number" => formatted_block_hash_or_number}) do
- with {:ok, block} <-
- param_block_hash_or_number_to_block(formatted_block_hash_or_number,
- necessity_by_association: %{
- [miner: :names] => :required,
- :uncles => :optional,
- :nephews => :optional,
- :rewards => :optional
- }
- ) do
- block_transaction_count = Chain.block_to_transaction_count(block)
-
- render(
- conn,
- "index.html",
- block: block,
- block_transaction_count: block_transaction_count,
- current_path: current_path(conn)
- )
- else
+ case param_block_hash_or_number_to_block(formatted_block_hash_or_number,
+ necessity_by_association: %{
+ [miner: :names] => :required,
+ :uncles => :optional,
+ :nephews => :optional,
+ :rewards => :optional
+ }
+ ) do
+ {:ok, block} ->
+ block_transaction_count = Chain.block_to_transaction_count(block.hash)
+
+ render(
+ conn,
+ "index.html",
+ block: block,
+ block_transaction_count: block_transaction_count,
+ current_path: current_path(conn)
+ )
+
{:error, {:invalid, :hash}} ->
not_found(conn)
@@ -117,19 +117,23 @@ defmodule BlockScoutWeb.BlockTransactionController do
end
defp param_block_hash_or_number_to_block("0x" <> _ = param, options) do
- with {:ok, hash} <- string_to_block_hash(param) do
- hash_to_block(hash, options)
- else
- :error -> {:error, {:invalid, :hash}}
+ case string_to_block_hash(param) do
+ {:ok, hash} ->
+ hash_to_block(hash, options)
+
+ :error ->
+ {:error, {:invalid, :hash}}
end
end
defp param_block_hash_or_number_to_block(number_string, options)
when is_binary(number_string) do
- with {:ok, number} <- BlockScoutWeb.Chain.param_to_block_number(number_string) do
- number_to_block(number, options)
- else
- {:error, :invalid} -> {:error, {:invalid, :number}}
+ case BlockScoutWeb.Chain.param_to_block_number(number_string) do
+ {:ok, number} ->
+ number_to_block(number, options)
+
+ {:error, :invalid} ->
+ {:error, {:invalid, :number}}
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex
index a89728949c..238f858769 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex
@@ -5,7 +5,7 @@ defmodule BlockScoutWeb.Chain.MarketHistoryChartController do
alias Explorer.ExchangeRates.Token
def show(conn, _params) do
- with true <- ajax?(conn) do
+ if ajax?(conn) do
exchange_rate = Market.get_exchange_rate(Explorer.coin()) || Token.null()
recent_market_history = Market.fetch_recent_history()
@@ -24,7 +24,7 @@ defmodule BlockScoutWeb.Chain.MarketHistoryChartController do
supply_data: available_supply(Chain.supply_for_days(), exchange_rate)
})
else
- _ -> unprocessable_entity(conn)
+ unprocessable_entity(conn)
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
index 40a0fd3bbb..ba5d547cf0 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
@@ -2,7 +2,7 @@ defmodule BlockScoutWeb.ChainController do
use BlockScoutWeb, :controller
alias BlockScoutWeb.ChainView
- alias Explorer.{Chain, PagingOptions, Repo}
+ alias Explorer.{Chain, PagingOptions}
alias Explorer.Chain.{Address, Block, Transaction}
alias Explorer.Chain.Supply.RSK
alias Explorer.Counters.AverageBlockTime
@@ -52,6 +52,8 @@ defmodule BlockScoutWeb.ChainController do
end
end
+ def search(conn, _), do: not_found(conn)
+
def token_autocomplete(conn, %{"q" => term}) when is_binary(term) do
if term == "" do
json(conn, "{}")
@@ -72,9 +74,15 @@ defmodule BlockScoutWeb.ChainController do
def chain_blocks(conn, _params) do
if ajax?(conn) do
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()
- |> Repo.preload([[miner: :names], :transactions, :rewards])
|> Enum.map(fn block ->
%{
chain_block_html:
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex
index b001093c6e..a98e380e67 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex
@@ -6,7 +6,7 @@ defmodule BlockScoutWeb.RecentTransactionsController do
alias Phoenix.View
def index(conn, _params) do
- with true <- ajax?(conn) do
+ if ajax?(conn) do
recent_transactions =
Chain.recent_collated_transactions(
necessity_by_association: %{
@@ -29,7 +29,7 @@ defmodule BlockScoutWeb.RecentTransactionsController do
json(conn, %{transactions: transactions})
else
- _ -> unprocessable_entity(conn)
+ unprocessable_entity(conn)
end
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
index 70ec6219f3..16b0122c5b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
@@ -30,15 +30,18 @@ defmodule BlockScoutWeb.SmartContractController do
end
end
+ def index(conn, _), do: not_found(conn)
+
def show(conn, params) do
with true <- ajax?(conn),
{:ok, address_hash} <- Chain.string_to_address_hash(params["id"]),
- {:ok, _address} <- Chain.find_contract_address(address_hash),
- outputs =
- Reader.query_function(
- address_hash,
- %{name: params["function_name"], args: params["args"]}
- ) do
+ :ok <- Chain.check_contract_address_exists(address_hash) do
+ outputs =
+ Reader.query_function(
+ address_hash,
+ %{name: params["function_name"], args: params["args"]}
+ )
+
conn
|> put_status(200)
|> put_layout(false)
@@ -51,7 +54,7 @@ defmodule BlockScoutWeb.SmartContractController do
:error ->
unprocessable_entity(conn)
- {:error, :not_found} ->
+ :not_found ->
not_found(conn)
_ ->
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
index 1bedf97c1d..3f849c0e7c 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
@@ -62,15 +62,15 @@ defmodule BlockScoutWeb.TransactionController do
def show(conn, %{"id" => id}) do
with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(id),
- {:ok, %Chain.Transaction{} = transaction} <- Chain.hash_to_transaction(transaction_hash) do
- if Chain.transaction_has_token_transfers?(transaction.hash) do
+ :ok <- Chain.check_transaction_exists(transaction_hash) do
+ if Chain.transaction_has_token_transfers?(transaction_hash) do
redirect(conn, to: transaction_token_transfer_path(conn, :index, id))
else
redirect(conn, to: transaction_internal_transaction_path(conn, :index, id))
end
else
: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
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex
index 159d144cdd..ca154a0136 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex
@@ -10,7 +10,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do
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 =
Keyword.merge(
[
@@ -24,7 +24,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
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)
@@ -37,7 +37,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
transaction_internal_transaction_path(
conn,
:index,
- transaction,
+ hash,
Map.delete(next_page_params, "type")
)
end
@@ -66,7 +66,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
|> put_view(TransactionView)
|> render("invalid.html", transaction_hash: hash_string)
- {:error, :not_found} ->
+ :not_found ->
conn
|> put_status(404)
|> put_view(TransactionView)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex
index 0a87d12493..e076b9ee7b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex
@@ -11,7 +11,9 @@ defmodule BlockScoutWeb.TransactionLogController do
def index(conn, %{"transaction_id" => transaction_hash_string, "type" => "JSON"} = params) do
with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string),
{:ok, transaction} <-
- Chain.hash_to_transaction(transaction_hash) do
+ Chain.hash_to_transaction(transaction_hash,
+ necessity_by_association: %{[to_address: :smart_contract] => :optional}
+ ) do
full_options =
Keyword.merge(
[
@@ -22,7 +24,7 @@ defmodule BlockScoutWeb.TransactionLogController do
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)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex
index 3d090e8a9b..250a6b4442 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_raw_trace_controller.ex
@@ -19,7 +19,7 @@ defmodule BlockScoutWeb.TransactionRawTraceController do
:token_transfers => :optional
}
) do
- internal_transactions = Chain.transaction_to_internal_transactions(transaction)
+ internal_transactions = Chain.transaction_to_internal_transactions(hash)
render(
conn,
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex
index cfb215da3e..585a01301f 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex
@@ -10,8 +10,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do
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 =
Keyword.merge(
[
@@ -24,7 +23,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
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)
@@ -34,7 +33,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
nil
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
items =
@@ -62,7 +61,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
|> put_view(TransactionView)
|> render("invalid.html", transaction_hash: hash_string)
- {:error, :not_found} ->
+ :not_found ->
conn
|> put_status(404)
|> put_view(TransactionView)
diff --git a/apps/block_scout_web/lib/block_scout_web/csp_header.ex b/apps/block_scout_web/lib/block_scout_web/csp_header.ex
index a29e87a146..199ee9f189 100644
--- a/apps/block_scout_web/lib/block_scout_web/csp_header.ex
+++ b/apps/block_scout_web/lib/block_scout_web/csp_header.ex
@@ -13,8 +13,8 @@ defmodule BlockScoutWeb.CSPHeader do
"content-security-policy" => "\
connect-src 'self' #{websocket_endpoints(conn)}; \
default-src 'self';\
- script-src 'self' 'unsafe-inline' 'unsafe-eval' https://nico-amsterdam.github.io;\
- style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com https://nico-amsterdam.github.io;\
+ script-src 'self' 'unsafe-inline' 'unsafe-eval';\
+ style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com;\
img-src 'self' 'unsafe-inline' 'unsafe-eval' data:;\
font-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.gstatic.com data:;\
"
diff --git a/apps/block_scout_web/lib/block_scout_web/notifier.ex b/apps/block_scout_web/lib/block_scout_web/notifier.ex
index 2fbe17537b..aa47163c98 100644
--- a/apps/block_scout_web/lib/block_scout_web/notifier.ex
+++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex
@@ -126,7 +126,7 @@ defmodule BlockScoutWeb.Notifier do
"""
def broadcast_blocks_indexed_ratio(ratio, finished?) do
Endpoint.broadcast("blocks:indexing", "index_status", %{
- ratio: ratio,
+ ratio: Decimal.to_string(ratio),
finished: finished?
})
end
diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex
index 4f5a8e1bed..7a1f5b3ed9 100644
--- a/apps/block_scout_web/lib/block_scout_web/router.ex
+++ b/apps/block_scout_web/lib/block_scout_web/router.ex
@@ -261,6 +261,6 @@ defmodule BlockScoutWeb.Router do
get("/api_docs", APIDocsController, :index)
get("/eth_rpc_api_docs", APIDocsController, :eth_rpc)
- get("/:page", PageNotFoundController, :index)
+ get("/*path", PageNotFoundController, :index)
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/schema/types.ex b/apps/block_scout_web/lib/block_scout_web/schema/types.ex
index 029b322f9c..aabd84b9aa 100644
--- a/apps/block_scout_web/lib/block_scout_web/schema/types.ex
+++ b/apps/block_scout_web/lib/block_scout_web/schema/types.ex
@@ -137,7 +137,7 @@ defmodule BlockScoutWeb.Schema.Types do
field(:r, :decimal)
field(:s, :decimal)
field(:status, :status)
- field(:v, :integer)
+ field(:v, :decimal)
field(:value, :wei)
field(:from_address_hash, :address_hash)
field(:to_address_hash, :address_hash)
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
index 9680faa2a8..56f1a2bbb2 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
@@ -21,7 +21,7 @@
<%= if @total_supply do %>
- (<%= balance_percentage(@address, @total_supply) %>)
+ <%= balance_percentage(@address, @total_supply) %>
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
index 3aaab46ad5..c594915d9f 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
@@ -38,7 +38,7 @@
-
+ <%= render BlockScoutWeb.CommonComponentsView, "_table-loader.html" %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
index 3cb95a5331..9f20f28458 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
@@ -79,18 +79,20 @@
<%= gettext("Incoming Transactions") %>
<% else %>
- <%= Cldr.Number.to_string!(@transaction_count, format: "#,###") %>
+ <%= BlockScoutWeb.Cldr.Number.to_string!(@transaction_count, format: "#,###") %>
<%= gettext("Transactions Sent") %>
<% end %>
-
- <%= gettext("Last Balance Update: Block #") %><%= @address.fetched_coin_balance_block_number %>
-
+ <%= if @address.fetched_coin_balance_block_number do %>
+
+ <%= gettext("Last Balance Update: Block #") %><%= @address.fetched_coin_balance_block_number %>
+
+ <% end %>
<%= if validator?(@validation_count) do %>
- <%= Cldr.Number.to_string!(@validation_count, format: "#,###") %>
+ <%= BlockScoutWeb.Cldr.Number.to_string!(@validation_count, format: "#,###") %>
<%= gettext("Blocks Validated") %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
index 6b9459f5b3..2e71dd22ca 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
@@ -40,7 +40,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
index 340765a97f..e8d6501e02 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
@@ -46,14 +46,18 @@
<%= @address.smart_contract.evm_version %>
<% end %>
- <%= if @address.smart_contract.constructor_arguments do %>
-
- <%= gettext "Constructor arguments" %>
- <%= @address.smart_contract.constructor_arguments %>
-
- <% end %>
-
+ <%= if @address.smart_contract.constructor_arguments do %>
+
+
+
<%= gettext "Constructor Arguments" %>
+
+
+
<%= raw(format_constructor_arguments(@address.smart_contract)) %>
+
+
+
+ <% end %>
<%= gettext "Contract source code" %>
@@ -116,7 +120,7 @@
<%= gettext "External libraries" %>
-
<%= format_external_libraries(@address.smart_contract.external_libraries) %>
+ <%= raw(format_external_libraries(@address.smart_contract.external_libraries)) %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex
index 3bc2e7fe9b..f18638db0d 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex
@@ -66,7 +66,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
index 1b5cb5c4fd..e49adf8801 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
@@ -11,6 +11,80 @@
) %>
+ <%= case decode(@log, @log.transaction) do %>
+ <% {:error, :contract_not_verified} -> %>
+ <%= gettext "Decoded" %>
+
+
+ <%= gettext "To see decoded input data, the contract must be verified." %>
+ <%= case @log.transaction do %>
+ <% %{to_address: %{hash: hash}} -> %>
+ <%= gettext "Verify the contract " %>
<%= gettext "here" %>
+ <% _ -> %>
+ <%= nil %>
+ <% end %>
+
+ <% {:error, :could_not_decode} -> %>
+ <%= gettext "Decoded" %>
+
+
+ <%= gettext "Failed to decode log data." %>
+
+ <% {:ok, method_id, text, mapping} -> %>
+ <%= gettext "Decoded" %>
+
+
+
+
" class="table thead-light table-bordered">
+
+
+ <%= gettext "Name" %>
+ <%= gettext "Type" %>
+ <%= gettext "Indexed?" %>
+ <%= gettext "Data" %>
+
+ <%= for {name, type, indexed?, value} <- mapping do %>
+
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
+ <% :error -> %>
+ <%= nil %>
+ <% copy_text -> %>
+
+
+
+
+
+ <% end %>
+
+ <%= name %>
+ <%= type %>
+ <%= indexed? %>
+
+ <%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %>
+
+
+ <% end %>
+
+
+ <% _ -> %>
+ <%= nil %>
+ <% end %>
<%= gettext "Topics" %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
index 3a44e0cb2d..fabbc7f7d8 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
@@ -27,7 +27,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
index 840d9cc1da..8510bdca64 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
@@ -19,7 +19,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex
index c2ab502bf0..738d70883d 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex
@@ -21,7 +21,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
index c3a4c94129..83c5454627 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
@@ -65,7 +65,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex
index 3f85f03aba..03b37369bc 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex
@@ -22,7 +22,9 @@
<%= gettext "Something went wrong, click to reload." %>
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex
index 92b91ce287..dd8a3ed093 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex
@@ -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, "_tile-loader.html" %>
+
<%= gettext "There are no blocks." %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex
index 24b2d9e61a..65e785920f 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex
@@ -57,7 +57,7 @@
<%= gettext "Difficulty" %>
- <%= @block.difficulty |> Cldr.Number.to_string! %>
+ <%= @block.difficulty |> BlockScoutWeb.Cldr.Number.to_string! %>
@@ -65,7 +65,7 @@
<%= gettext "Total Difficulty" %>
- <%= @block.total_difficulty |> Cldr.Number.to_string! %>
+ <%= @block.total_difficulty |> BlockScoutWeb.Cldr.Number.to_string! %>
@@ -97,14 +97,14 @@
<%= gettext "Gas Used" %>
- <%= @block.gas_used |> Cldr.Number.to_string! %>
- (<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> Cldr.Number.to_string!(format: "#.#%") %>)
+ <%= @block.gas_used |> BlockScoutWeb.Cldr.Number.to_string! %>
+ (<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> BlockScoutWeb.Cldr.Number.to_string!(format: "#.#%") %>)
<%= gettext "Gas Limit" %>
- <%= Cldr.Number.to_string!(@block.gas_limit) %>
+ <%= BlockScoutWeb.Cldr.Number.to_string!(@block.gas_limit) %>
<% end %>
@@ -146,10 +146,10 @@
<%= gettext "Gas Used" %>
- <%= @block.gas_used |> Cldr.Number.to_string! %>
- (<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> Cldr.Number.to_string!(format: "#.#%") %>)
+ <%= @block.gas_used |> BlockScoutWeb.Cldr.Number.to_string! %>
+ (<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> BlockScoutWeb.Cldr.Number.to_string!(format: "#.#%") %>)
-
<%= @block.gas_limit |> Cldr.Number.to_string! %><%= gettext "Gas Limit" %>
+
<%= @block.gas_limit |> BlockScoutWeb.Cldr.Number.to_string! %><%= gettext "Gas Limit" %>
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
index a497ab1b7e..e0847cac86 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
@@ -29,7 +29,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
index 0c29001697..8285d429e0 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
@@ -5,7 +5,7 @@
-
+
@@ -56,7 +56,7 @@
<%= gettext "Total transactions" %>
- <%= Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %>
+ <%= BlockScoutWeb.Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %>
@@ -64,7 +64,7 @@
<%= gettext "Total blocks" %>
- <%= Cldr.Number.to_string!(@block_count, format: "#,###") %>
+ <%= BlockScoutWeb.Cldr.Number.to_string!(@block_count, format: "#,###") %>
@@ -72,7 +72,7 @@
<%= gettext "Wallet addresses" %>
- <%= Cldr.Number.to_string!(@address_count, format: "#,###") %>
+ <%= BlockScoutWeb.Cldr.Number.to_string!(@address_count, format: "#,###") %>
@@ -91,8 +91,8 @@
<%= gettext "Something went wrong, click to reload." %>
-
-
+
+
@@ -117,12 +117,8 @@
<%= gettext "Something went wrong, click to retry." %>
-
-
-
-
-
- <%= gettext("Loading...") %>
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex
index f9992c6d86..dfe7c51f30 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex
@@ -14,15 +14,14 @@
+
+
+
+
+
+
-
-<%= render BlockScoutWeb.LayoutView, "_network_selector.html" %>
\ No newline at end of file
+<%= render BlockScoutWeb.LayoutView, "_network_selector.html" %>
+
\ No newline at end of file
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
index b3b6ba0665..6c0281f5c7 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
@@ -16,14 +16,15 @@
">
-
-
-
-
<%= render_existing(@view_module, "_metatags.html", assigns) || render("_default_title.html") %>
+
<%= if not Explorer.Chain.finished_indexing?() do %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
index 4c97be61e1..e819285629 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
@@ -23,13 +23,8 @@
<%= gettext "There are no pending transactions." %>
-
-
-
-
-
-
- <%= gettext("Loading") %>...
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/tokens/holder/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/tokens/holder/index.html.eex
index 3b24912dd5..8e83021c80 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/tokens/holder/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/tokens/holder/index.html.eex
@@ -28,7 +28,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex
index da834dbc88..1e78b11353 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex
@@ -27,7 +27,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex
index 980cc4b05a..addaa0c359 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex
@@ -26,7 +26,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
index f009eeb2b3..9e68d7e1bd 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
@@ -1,4 +1,5 @@
-" class="table thead-light table-bordered table-responsive transaction-info-table">
+
+
" class="table thead-light table-bordered">
<%= gettext "Method Id" %>
0x<%= @method_id %>
@@ -7,49 +8,52 @@
Call
<%= @text %>
-
+
+
<%= unless Enum.empty?(@mapping) do %>
- " class="table thead-light table-bordered table-responsive">
-
-
- <%= gettext "Name" %>
- <%= gettext "Type" %>
- <%= gettext "Data" %>
-
- <%= for {name, type, value} <- @mapping do %>
+
+
" class="table thead-light table-bordered">
+
+
+ <%= gettext "Name" %>
+ <%= gettext "Type" %>
+ <%= gettext "Data" %>
-
- <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
- <% :error -> %>
- <%= nil %>
- <% copy_text -> %>
-
-
-
-
-
- <% end %>
-
- <%= name %>
- <%= type %>
-
- <%= case BlockScoutWeb.ABIEncodedValueView.value_html(type, value) do %>
- <% :error -> %>
-
- <%= gettext "Error rendering value" %>
-
- <% value -> %>
- <%= value %>
+ <%= for {name, type, value} <- @mapping do %>
+
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
+ <% :error -> %>
+ <%= nil %>
+ <% copy_text -> %>
+
+
+
+
+
<% end %>
-
-
- <% end %>
-
+
+
<%= name %>
+
<%= type %>
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.value_html(type, value) do %>
+ <% :error -> %>
+
+ <%= gettext "Error rendering value" %>
+
+ <% value -> %>
+ <%= value %>
+ <% end %>
+
+
+ <% end %>
+
+
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_tile.html.eex
index d6882801ad..b70cbbb1fb 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_tile.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_tile.html.eex
@@ -26,11 +26,11 @@
- <%= value(@transaction, include_label: false) %>
+ <%= value(@transaction, include_label: false) %>
<%= gettext "Ether" %>
- <%= formatted_fee(@transaction, denomination: :ether, include_label: false) %>
+ <%= formatted_fee(@transaction, denomination: :ether, include_label: false) %>
<%= gettext "TX Fee" %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_token_transfer.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_token_transfer.html.eex
index 73038c15db..3afa468b54 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/_token_transfer.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/_token_transfer.html.eex
@@ -19,7 +19,7 @@
<%= @token_transfer |> BlockScoutWeb.AddressView.address_partial_selector(:to, @address, true) |> BlockScoutWeb.RenderHelpers.render_partial() %>
-
+
<%= token_transfer_amount(@token_transfer) %>
<%= link(token_symbol(@token_transfer.token), to: token_path(BlockScoutWeb.Endpoint, :show, @token_transfer.token.contract_address_hash)) %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
index 18928915f2..bce59eb00b 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
@@ -28,7 +28,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
index fe347ee904..e804ec81d9 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
@@ -177,7 +177,7 @@
<%= token_type_name(type)%><%= gettext " Token Transfer" %>
- <%= for transfer <- transaction_with_transfers.token_transfers do %>
+ <%= for transfer <- aggregate_token_transfers(transaction_with_transfers.token_transfers) do %>
<%= token_transfer_amount(transfer) %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
index e6623b4061..70162a3be8 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
@@ -16,7 +16,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
index 5a52821601..c63502669b 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
@@ -1,7 +1,7 @@
- <%= gettext "Address" %>
-
+ <%= gettext "Address" %>
+
<%= link(
@log.address,
@@ -11,10 +11,10 @@
) %>
- <%= gettext "Decoded" %>
-
<%= case decode(@log, @transaction) do %>
<% {:error, :contract_not_verified} -> %>
+ <%= gettext "Decoded" %>
+
<%= gettext "To see decoded input data, the contract must be verified." %>
<%= case @transaction do %>
@@ -25,10 +25,16 @@
<% end %>
<% {:error, :could_not_decode} -> %>
+ <%= gettext "Decoded" %>
+
<%= gettext "Failed to decode log data." %>
+ <% {:error, :no_matching_function} -> %>
+ <%= nil %>
<% {:ok, method_id, text, mapping} -> %>
+ <%= gettext "Decoded" %>
+
- " class="table thead-light table-bordered table-responsive">
-
-
- <%= gettext "Name" %>
- <%= gettext "Type" %>
- <%= gettext "Indexed?" %>
- <%= gettext "Data" %>
-
- <%= for {name, type, indexed?, value} <- mapping do %>
+
+
" class="table thead-light table-bordered">
-
- <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
- <% :error -> %>
- <%= nil %>
- <% copy_text -> %>
-
-
-
-
-
- <% end %>
-
- <%= name %>
- <%= type %>
- <%= indexed? %>
-
- <%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %>
-
-
- <% end %>
-
+
+
<%= gettext "Name" %>
+
<%= gettext "Type" %>
+
<%= gettext "Indexed?" %>
+
<%= gettext "Data" %>
+
+ <%= for {name, type, indexed?, value} <- mapping do %>
+
+
+ <%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
+ <% :error -> %>
+ <%= nil %>
+ <% copy_text -> %>
+
+
+
+
+
+ <% end %>
+
+ <%= name %>
+ <%= type %>
+ <%= indexed? %>
+
+ <%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %>
+
+
+ <% end %>
+
+
<% _ -> %>
<%= nil %>
<% end %>
- <%= gettext "Topics" %>
-
+ <%= gettext "Topics" %>
+
<%= unless is_nil(@log.first_topic) do %>
@@ -109,10 +117,10 @@
<% end %>
-
+
<%= gettext "Data" %>
-
+
<%= unless is_nil(@log.data) do %>
<%= @log.data %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
index 3c84e7c4f9..17f480b439 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
@@ -19,7 +19,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
index d40dedd414..8d356a450a 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
@@ -18,7 +18,9 @@
-
+
+ <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
+
<%= 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 %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
index 5de263f820..57c6e11da7 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
@@ -1,6 +1,7 @@
defmodule BlockScoutWeb.AddressContractView do
use BlockScoutWeb, :view
+ alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain.{Address, Data, InternalTransaction}
def render("scripts.html", %{conn: conn}) do
@@ -21,9 +22,44 @@ defmodule BlockScoutWeb.AddressContractView do
def format_optimization_text(true), do: gettext("true")
def format_optimization_text(false), do: gettext("false")
+ def format_constructor_arguments(contract) do
+ constructor_abi = Enum.find(contract.abi, fn el -> el["type"] == "constructor" && el["inputs"] != [] end)
+
+ input_types = Enum.map(constructor_abi["inputs"], &FunctionSelector.parse_specification_type/1)
+
+ {_, result} =
+ contract.constructor_arguments
+ |> decode_data(input_types)
+ |> Enum.zip(constructor_abi["inputs"])
+ |> Enum.reduce({0, "#{contract.constructor_arguments}\n\n"}, fn {val, %{"type" => type}}, {count, acc} ->
+ formatted_val =
+ if is_binary(val) do
+ Base.encode16(val, case: :lower)
+ else
+ val
+ end
+
+ {count + 1, "#{acc}Arg [#{count}] (#{type} ) : #{formatted_val}\n"}
+ end)
+
+ result
+ rescue
+ _ -> contract.constructor_arguments
+ end
+
+ defp decode_data("0x" <> encoded_data, types) do
+ decode_data(encoded_data, types)
+ end
+
+ defp decode_data(encoded_data, types) do
+ encoded_data
+ |> Base.decode16!(case: :mixed)
+ |> TypeDecoder.decode_raw(types)
+ end
+
def format_external_libraries(libraries) do
Enum.reduce(libraries, "", fn %{name: name, address_hash: address_hash}, acc ->
- acc <> name <> " : " <> address_hash <> "\n"
+ "#{acc}#{name} : #{address_hash} \n"
end)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
index 7155e65206..3cdfaf1f9b 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
@@ -1,3 +1,9 @@
defmodule BlockScoutWeb.AddressLogsView do
use BlockScoutWeb, :view
+
+ alias Explorer.Chain.Log
+
+ def decode(log, transaction) do
+ Log.decode(log, transaction)
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_view.ex
index f93b8bcb0b..15405beecb 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/address_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/address_view.ex
@@ -222,7 +222,7 @@ defmodule BlockScoutWeb.AddressView do
def incoming_transaction_count(address_hash) do
address_hash
|> Chain.address_to_incoming_transaction_count()
- |> Cldr.Number.to_string!(format: "#,###")
+ |> BlockScoutWeb.Cldr.Number.to_string!(format: "#,###")
end
def trimmed_hash(%Hash{} = hash) do
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/rpc/stats_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/rpc/stats_view.ex
index 8d88181a5d..bdc5e28b0e 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/rpc/stats_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/rpc/stats_view.ex
@@ -4,7 +4,7 @@ defmodule BlockScoutWeb.API.RPC.StatsView do
alias BlockScoutWeb.API.RPC.RPCView
def render("tokensupply.json", token_supply) do
- RPCView.render("show.json", data: token_supply)
+ RPCView.render("show.json", data: Decimal.to_string(token_supply))
end
def render("ethsupply.json", %{total_supply: total_supply}) do
diff --git a/apps/block_scout_web/lib/block_scout_web/views/block_view.ex b/apps/block_scout_web/lib/block_scout_web/views/block_view.ex
index e475e7ace9..f30f385c86 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/block_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/block_view.ex
@@ -15,7 +15,7 @@ defmodule BlockScoutWeb.BlockView do
|> Enum.map(&Decimal.to_float(Wei.to(&1.gas_price, :gwei)))
|> mean()
|> Kernel.||(0)
- |> Cldr.Number.to_string!()
+ |> BlockScoutWeb.Cldr.Number.to_string!()
unit_text = gettext("Gwei")
@@ -33,7 +33,7 @@ defmodule BlockScoutWeb.BlockView do
# We do this to trick Dialyzer to not complain about non-local returns caused by bug in Cldr.Unit.to_string! spec
case :erlang.phash2(1, 1) do
0 ->
- Cldr.Unit.to_string!(unit)
+ BlockScoutWeb.Cldr.Unit.to_string!(unit)
1 ->
# does not occur
@@ -42,7 +42,7 @@ defmodule BlockScoutWeb.BlockView do
end
def formatted_gas(gas, format \\ []) do
- Cldr.Number.to_string!(gas, format)
+ BlockScoutWeb.Cldr.Number.to_string!(gas, format)
end
def formatted_timestamp(%Block{timestamp: timestamp}) do
diff --git a/apps/block_scout_web/lib/block_scout_web/views/cldr/number.ex b/apps/block_scout_web/lib/block_scout_web/views/cldr_helper/number.ex
similarity index 79%
rename from apps/block_scout_web/lib/block_scout_web/views/cldr/number.ex
rename to apps/block_scout_web/lib/block_scout_web/views/cldr_helper/number.ex
index 2484646a74..e5b946e416 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/cldr/number.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/cldr_helper/number.ex
@@ -1,4 +1,4 @@
-defmodule BlockScoutWeb.Cldr.Number do
+defmodule BlockScoutWeb.CldrHelper.Number do
@moduledoc """
Work-arounds for `Cldr.Number` bugs
"""
@@ -7,7 +7,7 @@ defmodule BlockScoutWeb.Cldr.Number do
# We do this to trick Dialyzer to not complain about non-local returns caused by bug in Cldr.Number.to_string spec
case :erlang.phash2(1, 1) do
0 ->
- Cldr.Number.to_string(decimal, options)
+ BlockScoutWeb.Cldr.Number.to_string(decimal, options)
1 ->
# does not occur
@@ -19,7 +19,7 @@ defmodule BlockScoutWeb.Cldr.Number do
# We do this to trick Dialyzer to not complain about non-local returns caused by bug in Cldr.Number.to_string! spec
case :erlang.phash2(1, 1) do
0 ->
- Cldr.Number.to_string!(decimal)
+ BlockScoutWeb.Cldr.Number.to_string!(decimal)
1 ->
# does not occur
@@ -31,7 +31,7 @@ defmodule BlockScoutWeb.Cldr.Number do
# We do this to trick Dialyzer to not complain about non-local returns caused by bug in Cldr.Number.to_string! spec
case :erlang.phash2(1, 1) do
0 ->
- Cldr.Number.to_string!(decimal, options)
+ BlockScoutWeb.Cldr.Number.to_string!(decimal, options)
1 ->
# does not occur
diff --git a/apps/block_scout_web/lib/block_scout_web/views/currency_helpers.ex b/apps/block_scout_web/lib/block_scout_web/views/currency_helpers.ex
index d79be3b31e..2aad5b013c 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/currency_helpers.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/currency_helpers.ex
@@ -3,7 +3,7 @@ defmodule BlockScoutWeb.CurrencyHelpers do
Helper functions for interacting with `t:BlockScoutWeb.ExchangeRates.USD.t/0` values.
"""
- alias BlockScoutWeb.Cldr.Number
+ alias BlockScoutWeb.CldrHelper.Number
@doc """
Formats the given integer value to a currency format.
diff --git a/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex b/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
index fe12f04302..46252f72ce 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
@@ -23,6 +23,7 @@ defmodule BlockScoutWeb.InternalTransactionView do
def type(%InternalTransaction{type: :call, call_type: :delegatecall}), do: gettext("Delegate Call")
def type(%InternalTransaction{type: :call, call_type: :staticcall}), do: gettext("Static Call")
def type(%InternalTransaction{type: :create}), do: gettext("Create")
+ def type(%InternalTransaction{type: :create2}), do: gettext("Create2")
def type(%InternalTransaction{type: :selfdestruct}), do: gettext("Self-Destruct")
def type(%InternalTransaction{type: :reward}), do: gettext("Reward")
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex b/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex
index 1ad70179bf..33569f3a97 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex
@@ -4,7 +4,7 @@ defmodule BlockScoutWeb.Tokens.Helpers do
"""
alias BlockScoutWeb.{CurrencyHelpers}
- alias Explorer.Chain.{Address, Token, TokenTransfer}
+ alias Explorer.Chain.{Address, Token}
@doc """
Returns the token transfers' amount according to the token's type and decimals.
@@ -16,7 +16,7 @@ defmodule BlockScoutWeb.Tokens.Helpers do
When the token's type is ERC-721, the function will return a string with the token_id that
represents the ERC-721 token since this kind of token doesn't have amount and decimals.
"""
- def token_transfer_amount(%TokenTransfer{token: token, amount: amount, token_id: token_id}) do
+ def token_transfer_amount(%{token: token, amount: amount, token_id: token_id}) do
do_token_transfer_amount(token, amount, token_id)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex b/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
index 1ed50d28ab..53d64555dd 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
@@ -2,7 +2,7 @@ defmodule BlockScoutWeb.TransactionView do
use BlockScoutWeb, :view
alias BlockScoutWeb.{AddressView, BlockView, TabHelpers}
- alias Cldr.Number
+ alias BlockScoutWeb.Cldr.Number
alias Explorer.{Chain, Repo}
alias Explorer.Chain.Block.Reward
alias Explorer.Chain.{Address, Block, InternalTransaction, Transaction, Wei}
@@ -39,6 +39,46 @@ defmodule BlockScoutWeb.TransactionView do
if type, do: {type, transaction_with_transfers}
end
+ def aggregate_token_transfers(token_transfers) do
+ {transfers, nft_transfers} =
+ token_transfers
+ |> Enum.reduce({%{}, []}, fn token_transfer, acc ->
+ aggregate_reducer(token_transfer, acc)
+ end)
+
+ final_transfers = Map.values(transfers)
+
+ final_transfers ++ nft_transfers
+ end
+
+ defp aggregate_reducer(%{amount: amount} = token_transfer, {acc1, acc2}) when is_nil(amount) do
+ new_entry = %{
+ token: token_transfer.token,
+ amount: nil,
+ token_id: token_transfer.token_id
+ }
+
+ {acc1, [new_entry | acc2]}
+ end
+
+ defp aggregate_reducer(token_transfer, {acc1, acc2}) do
+ new_entry = %{
+ token: token_transfer.token,
+ amount: token_transfer.amount,
+ token_id: token_transfer.token_id
+ }
+
+ existing_entry = Map.get(acc1, token_transfer.token_contract_address, %{new_entry | amount: Decimal.new(0)})
+
+ new_acc1 =
+ Map.put(acc1, token_transfer.token_contract_address, %{
+ new_entry
+ | amount: Decimal.add(new_entry.amount, existing_entry.amount)
+ })
+
+ {new_acc1, acc2}
+ end
+
def token_type_name(type) do
case type do
:erc20 -> gettext("ERC-20 ")
@@ -100,7 +140,7 @@ defmodule BlockScoutWeb.TransactionView do
%Block{consensus: true} ->
{:ok, confirmations} = Chain.confirmations(block, named_arguments)
- Cldr.Number.to_string!(confirmations, format: "#,###")
+ BlockScoutWeb.Cldr.Number.to_string!(confirmations, format: "#,###")
end
end
@@ -156,7 +196,7 @@ defmodule BlockScoutWeb.TransactionView do
end
def gas(%type{gas: gas}) when is_transaction_type(type) do
- Cldr.Number.to_string!(gas)
+ BlockScoutWeb.Cldr.Number.to_string!(gas)
end
def skip_decoding?(transaction) do
diff --git a/apps/block_scout_web/lib/block_scout_web/views/wei_helpers.ex b/apps/block_scout_web/lib/block_scout_web/views/wei_helpers.ex
index 5cdbff8c0c..c9dfefa7b7 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/wei_helpers.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/wei_helpers.ex
@@ -5,7 +5,7 @@ defmodule BlockScoutWeb.WeiHelpers do
import BlockScoutWeb.Gettext
- alias BlockScoutWeb.Cldr
+ alias BlockScoutWeb.CldrHelper
alias Explorer.Chain.Wei
@valid_units ~w(wei gwei ether)a
@@ -60,9 +60,9 @@ defmodule BlockScoutWeb.WeiHelpers do
formatted_value =
if Decimal.cmp(converted_value, 1_000_000_000_000) == :gt do
- Cldr.Number.to_string!(converted_value, format: "0.###E+0")
+ CldrHelper.Number.to_string!(converted_value, format: "0.###E+0")
else
- Cldr.Number.to_string!(converted_value, format: "#,##0.##################")
+ CldrHelper.Number.to_string!(converted_value, format: "#,##0.##################")
end
if Keyword.get(options, :include_unit_label, true) do
diff --git a/apps/block_scout_web/mix.exs b/apps/block_scout_web/mix.exs
index e431d4ecf5..27a1e6aa74 100644
--- a/apps/block_scout_web/mix.exs
+++ b/apps/block_scout_web/mix.exs
@@ -50,7 +50,6 @@ defmodule BlockScoutWeb.Mixfile do
defp extra_applications,
do: [
- :ex_cldr,
:logger,
:runtime_tools
]
@@ -65,21 +64,23 @@ defmodule BlockScoutWeb.Mixfile do
# Integrates Absinthe subscriptions with Phoenix
{:absinthe_phoenix, git: "https://github.com/ayrat555/absinthe_phoenix.git", branch: "master"},
# Plug support for Absinthe
- {:absinthe_plug, git: "https://github.com/ayrat555/absinthe_plug.git", branch: "ab-allow-to-set-default-query"},
+ {:absinthe_plug, git: "https://github.com/ayrat555/absinthe_plug.git", branch: "ab-enable-default-query"},
# Absinthe support for the Relay framework
{:absinthe_relay, "~> 1.4"},
{:bypass, "~> 1.0", only: :test},
# To add (CORS)(https://www.w3.org/TR/cors/)
{:cors_plug, "~> 2.0"},
- {:credo, "1.0.0", only: :test, runtime: false},
+ {:credo, "~> 1.1", only: :test, runtime: false},
# For Absinthe to load data in batches
{:dataloader, "~> 1.0.0"},
{:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false},
# Need until https://github.com/absinthe-graphql/absinthe_relay/pull/125 is released, then can be removed
# The current `absinthe_relay` is compatible though as shown from that PR
{:ecto, "~> 3.0", override: true},
- {:ex_cldr_numbers, "~> 1.0"},
- {:ex_cldr_units, "~> 1.0"},
+ {:ex_cldr, "~> 2.7"},
+ {:ex_cldr_numbers, "~> 2.6"},
+ {:ex_cldr_units, "~> 2.5"},
+ {:cldr_utils, "~> 2.3"},
{:ex_machina, "~> 2.1", only: [:test]},
# Code coverage
{:excoveralls, "~> 0.10.0", only: [:test], github: "KronicDeth/excoveralls", branch: "circle-workflows"},
@@ -101,7 +102,7 @@ defmodule BlockScoutWeb.Mixfile do
{:phoenix, "~> 1.4"},
{:phoenix_ecto, "~> 4.0"},
{:phoenix_html, "~> 2.10"},
- {:phoenix_live_reload, "~> 1.0", only: [:dev]},
+ {:phoenix_live_reload, "~> 1.2", only: [:dev]},
{:phoenix_pubsub, "~> 1.0"},
# use `:cowboy` for WebServer with `:plug`
{:plug_cowboy, "~> 2.0"},
@@ -125,7 +126,7 @@ defmodule BlockScoutWeb.Mixfile do
{:spandex_datadog, "~> 0.4.0"},
# `:spandex` tracing of `:phoenix`
{:spandex_phoenix, "~> 0.3.1"},
- {:timex, "~> 3.4"},
+ {:timex, "~> 3.6"},
{:wallaby, "~> 0.22", only: [:test], runtime: false},
# `:cowboy` `~> 2.0` and Phoenix 1.4 compatibility
{:wobserver, "~> 0.2.0", github: "poanetwork/wobserver", branch: "support-https"},
diff --git a/apps/block_scout_web/package-lock.json b/apps/block_scout_web/package-lock.json
deleted file mode 100644
index 48e341a095..0000000000
--- a/apps/block_scout_web/package-lock.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "lockfileVersion": 1
-}
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot
index 61d7465f49..11cf715872 100644
--- a/apps/block_scout_web/priv/gettext/default.pot
+++ b/apps/block_scout_web/priv/gettext/default.pot
@@ -49,7 +49,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:144
+#: lib/block_scout_web/views/transaction_view.ex:184
msgid "(Awaiting internal transactions for status)"
msgstr ""
@@ -62,7 +62,7 @@ msgid "(query)"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:35
+#: lib/block_scout_web/templates/layout/app.html.eex:36
msgid "- We're indexing this chain right now. Some of the counts may be inaccurate."
msgstr ""
@@ -87,7 +87,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:56
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:70
msgid "Accounts"
msgstr ""
@@ -157,7 +157,7 @@ msgid "Block Height: %{height}"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:50
+#: lib/block_scout_web/templates/layout/app.html.eex:51
msgid "Block Mined, awaiting import..."
msgstr ""
@@ -178,19 +178,19 @@ msgstr ""
#, elixir-format
#: 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:20
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:30
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:34
msgid "Blocks"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:49
+#: lib/block_scout_web/templates/layout/app.html.eex:50
msgid "Blocks Indexed"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:32
-#: lib/block_scout_web/templates/address/overview.html.eex:95
+#: lib/block_scout_web/templates/address/overview.html.eex:97
#: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:311
msgid "Blocks Validated"
@@ -209,8 +209,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:37
-#: lib/block_scout_web/templates/address/overview.html.eex:144
-#: lib/block_scout_web/templates/address/overview.html.eex:152
+#: lib/block_scout_web/templates/address/overview.html.eex:146
+#: lib/block_scout_web/templates/address/overview.html.eex:154
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:115
msgid "Close"
@@ -258,7 +258,7 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:71
+#: lib/block_scout_web/templates/address_contract/index.html.eex:75
msgid "Contract ABI"
msgstr ""
@@ -276,12 +276,12 @@ msgid "Contract Address Pending"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:221
+#: lib/block_scout_web/views/transaction_view.ex:261
msgid "Contract Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:220
+#: lib/block_scout_web/views/transaction_view.ex:260
msgid "Contract Creation"
msgstr ""
@@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:59
+#: lib/block_scout_web/templates/address_contract/index.html.eex:63
msgid "Contract source code"
msgstr ""
@@ -319,7 +319,7 @@ msgid "Copy Txn Hash"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:105
+#: lib/block_scout_web/templates/address/overview.html.eex:107
msgid "Created by"
msgstr ""
@@ -328,14 +328,6 @@ msgstr ""
msgid "Curl"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
-msgid "Data"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@@ -364,19 +356,19 @@ msgid "Error trying to fetch balances."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:148
+#: lib/block_scout_web/views/transaction_view.ex:188
msgid "Error: %{reason}"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:146
+#: lib/block_scout_web/views/transaction_view.ex:186
msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
#, elixir-format
#: 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/layout/app.html.eex:55
+#: lib/block_scout_web/templates/layout/app.html.eex:56
#: 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/overview.html.eex:196
@@ -400,7 +392,7 @@ msgid "Fetching tokens..."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:26
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:40
msgid "Forked Blocks (Reorgs)"
msgstr ""
@@ -454,7 +446,7 @@ msgid "IN"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:51
+#: lib/block_scout_web/templates/layout/app.html.eex:52
msgid "Indexing Tokens"
msgstr ""
@@ -474,7 +466,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:306
-#: lib/block_scout_web/views/transaction_view.ex:274
+#: lib/block_scout_web/views/transaction_view.ex:314
msgid "Internal Transactions"
msgstr ""
@@ -486,7 +478,7 @@ msgid "Inventory"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:52
+#: lib/block_scout_web/templates/layout/app.html.eex:53
msgid "Less than"
msgstr ""
@@ -501,21 +493,21 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:312
-#: lib/block_scout_web/views/transaction_view.ex:275
+#: lib/block_scout_web/views/transaction_view.ex:315
msgid "Logs"
msgstr ""
#, elixir-format
#: 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:54
#: lib/block_scout_web/views/address_view.ex:121
#: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:129
-#: lib/block_scout_web/views/transaction_view.ex:129
+#: lib/block_scout_web/views/transaction_view.ex:169
+#: lib/block_scout_web/views/transaction_view.ex:169
msgid "Max of"
msgstr ""
@@ -555,9 +547,10 @@ msgid "Must be set to:"
msgstr ""
#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:50
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:52
msgid "Name"
msgstr ""
@@ -604,9 +597,9 @@ msgid "Parent Hash"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:44
-#: lib/block_scout_web/views/transaction_view.ex:143
-#: lib/block_scout_web/views/transaction_view.ex:177
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:58
+#: lib/block_scout_web/views/transaction_view.ex:183
+#: lib/block_scout_web/views/transaction_view.ex:217
msgid "Pending"
msgstr ""
@@ -622,13 +615,13 @@ msgstr ""
#, elixir-format
#: 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:55
msgid "Price"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:33
-#: lib/block_scout_web/templates/address/overview.html.eex:143
+#: lib/block_scout_web/templates/address/overview.html.eex:145
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:36
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106
msgid "QR Code"
@@ -669,8 +662,8 @@ msgstr ""
#, elixir-format
#: 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:119
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:122
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:139
msgid "Search"
msgstr ""
@@ -693,7 +686,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
-#: lib/block_scout_web/views/transaction_view.ex:145
+#: lib/block_scout_web/views/transaction_view.ex:185
msgid "Success"
msgstr ""
@@ -774,7 +767,7 @@ msgid "To"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:6
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation"
msgstr ""
@@ -798,7 +791,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
-#: lib/block_scout_web/views/transaction_view.ex:219
+#: lib/block_scout_web/views/transaction_view.ex:259
msgid "Token Transfer"
msgstr ""
@@ -808,7 +801,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35
-#: lib/block_scout_web/views/transaction_view.ex:273
+#: lib/block_scout_web/views/transaction_view.ex:313
msgid "Token Transfers"
msgstr ""
@@ -825,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
-msgid "Topics"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
@@ -848,7 +835,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:3
-#: lib/block_scout_web/views/transaction_view.ex:222
+#: lib/block_scout_web/views/transaction_view.ex:262
msgid "Transaction"
msgstr ""
@@ -873,7 +860,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: 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:49
#: lib/block_scout_web/views/address_view.ex:305
msgid "Transactions"
msgstr ""
@@ -900,7 +887,7 @@ msgstr ""
#, elixir-format
#: 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:37
msgid "Uncles"
msgstr ""
@@ -915,7 +902,7 @@ msgid "Used"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:39
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:53
msgid "Validated"
msgstr ""
@@ -996,12 +983,12 @@ msgid "Yes"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:111
+#: lib/block_scout_web/templates/address/overview.html.eex:113
msgid "at"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/address_contract_view.ex:22
+#: lib/block_scout_web/views/address_contract_view.ex:23
msgid "false"
msgstr ""
@@ -1019,7 +1006,7 @@ msgid "string"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/address_contract_view.ex:21
+#: lib/block_scout_web/views/address_contract_view.ex:22
msgid "true"
msgstr ""
@@ -1039,14 +1026,7 @@ msgid "Delegate Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/block/_tile.html.eex:47
-#: lib/block_scout_web/templates/chain/_block.html.eex:23
#: lib/block_scout_web/views/internal_transaction_view.ex:27
-msgid "Reward"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct"
msgstr ""
@@ -1058,7 +1038,6 @@ msgstr ""
#, elixir-format
#: 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:125
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:21
msgid "Loading..."
msgstr ""
@@ -1069,22 +1048,17 @@ msgid "Loading...."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:64
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "APIs"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:68
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:82
msgid "GraphQL"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/pending_transaction/index.html.eex:32
-msgid "Loading"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:73
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:87
msgid "RPC"
msgstr ""
@@ -1134,48 +1108,41 @@ msgid "Static Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:28
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:34
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:16
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:28
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:36
msgid "Decoded"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
-msgid "Indexed?"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
-msgid "Type"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
msgid "Method Id"
msgstr ""
#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_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."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1
-msgid "Transaction Info"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgid "Transaction Inputs"
msgstr ""
#, 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_log/_logs.html.eex:22
msgid "Verify the contract "
msgstr ""
#, 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_log/_logs.html.eex:22
msgid "here"
@@ -1187,26 +1154,10 @@ msgid "Failed to decode input data."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
-msgid "Copy Value"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
-msgid "Failed to decode log data."
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
-msgid "Log Data"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
@@ -1277,7 +1228,7 @@ msgid "There are no pending transactions."
msgstr ""
#, 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."
msgstr ""
@@ -1407,17 +1358,17 @@ msgid "Support"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:73
+#: lib/block_scout_web/templates/address_contract/index.html.eex:77
msgid "Copy ABI"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:89
+#: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:61
+#: lib/block_scout_web/templates/address_contract/index.html.eex:65
msgid "Copy Source Code"
msgstr ""
@@ -1432,7 +1383,7 @@ msgid "Contract Libraries"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:88
+#: lib/block_scout_web/templates/address/overview.html.eex:89
msgid "Last Balance Update: Block #"
msgstr ""
@@ -1478,13 +1429,13 @@ msgid "Incoming Transactions"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:119
+#: lib/block_scout_web/templates/address/overview.html.eex:121
msgid "Error: Could not determine contract creator."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:96
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:100
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:116
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:120
msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr ""
@@ -1548,7 +1499,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:7
-#: lib/block_scout_web/views/transaction_view.ex:276
+#: lib/block_scout_web/views/transaction_view.ex:316
msgid "Raw Trace"
msgstr ""
@@ -1559,7 +1510,7 @@ msgstr ""
#, elixir-format
#:
-#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:40
+#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:39
msgid "Page"
msgstr ""
@@ -1577,7 +1528,7 @@ msgstr ""
#, elixir-format
#:
-#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:40
+#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:39
msgid "of"
msgstr ""
@@ -1587,27 +1538,27 @@ msgid "Block Details"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:101
+#: lib/block_scout_web/templates/address_contract/index.html.eex:105
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:87
+#: lib/block_scout_web/templates/address_contract/index.html.eex:91
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:93
+#: lib/block_scout_web/templates/address_contract/index.html.eex:97
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:103
+#: lib/block_scout_web/templates/address_contract/index.html.eex:107
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:94
+#: lib/block_scout_web/templates/address_contract/index.html.eex:98
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
@@ -1710,7 +1661,7 @@ msgid "ETH RPC API Documentation"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:78
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:92
msgid "Eth RPC"
msgstr ""
@@ -1745,8 +1696,8 @@ msgid "here."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_token/index.html.eex:26
-#: lib/block_scout_web/templates/address_transaction/index.html.eex:72
+#: lib/block_scout_web/templates/address_token/index.html.eex:28
+#: lib/block_scout_web/templates/address_transaction/index.html.eex:74
msgid "CSV"
msgstr ""
@@ -1756,22 +1707,17 @@ msgid "Change Network"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:51
-msgid "Constructor arguments"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:44
+#: lib/block_scout_web/views/transaction_view.ex:84
msgid "ERC-20 "
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:45
+#: lib/block_scout_web/views/transaction_view.ex:85
msgid "ERC-721 "
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:116
+#: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "External libraries"
msgstr ""
@@ -1804,3 +1750,67 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost"
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_contract/index.html.eex:53
+msgid "Constructor Arguments"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:63
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:65
+msgid "Copy Value"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/views/internal_transaction_view.ex:26
+msgid "Create2"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:53
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:118
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:55
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:121
+msgid "Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:31
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:31
+msgid "Failed to decode log data."
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:52
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:54
+msgid "Indexed?"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
+msgid "Log Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/block/_tile.html.eex:47
+#: lib/block_scout_web/templates/chain/_block.html.eex:23
+#: lib/block_scout_web/views/internal_transaction_view.ex:28
+msgid "Reward"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:88
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:91
+msgid "Topics"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:51
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:53
+msgid "Type"
+msgstr ""
diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
index 5333eb95aa..f9e5473ee4 100644
--- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
+++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
@@ -49,7 +49,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:144
+#: lib/block_scout_web/views/transaction_view.ex:184
msgid "(Awaiting internal transactions for status)"
msgstr ""
@@ -62,7 +62,7 @@ msgid "(query)"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:35
+#: lib/block_scout_web/templates/layout/app.html.eex:36
msgid "- We're indexing this chain right now. Some of the counts may be inaccurate."
msgstr ""
@@ -87,7 +87,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:56
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:70
msgid "Accounts"
msgstr ""
@@ -157,7 +157,7 @@ msgid "Block Height: %{height}"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:50
+#: lib/block_scout_web/templates/layout/app.html.eex:51
msgid "Block Mined, awaiting import..."
msgstr ""
@@ -178,19 +178,19 @@ msgstr ""
#, elixir-format
#: 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:20
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:30
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:34
msgid "Blocks"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:49
+#: lib/block_scout_web/templates/layout/app.html.eex:50
msgid "Blocks Indexed"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:32
-#: lib/block_scout_web/templates/address/overview.html.eex:95
+#: lib/block_scout_web/templates/address/overview.html.eex:97
#: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:311
msgid "Blocks Validated"
@@ -209,8 +209,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:37
-#: lib/block_scout_web/templates/address/overview.html.eex:144
-#: lib/block_scout_web/templates/address/overview.html.eex:152
+#: lib/block_scout_web/templates/address/overview.html.eex:146
+#: lib/block_scout_web/templates/address/overview.html.eex:154
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:115
msgid "Close"
@@ -258,7 +258,7 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:71
+#: lib/block_scout_web/templates/address_contract/index.html.eex:75
msgid "Contract ABI"
msgstr ""
@@ -276,12 +276,12 @@ msgid "Contract Address Pending"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:221
+#: lib/block_scout_web/views/transaction_view.ex:261
msgid "Contract Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:220
+#: lib/block_scout_web/views/transaction_view.ex:260
msgid "Contract Creation"
msgstr ""
@@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:59
+#: lib/block_scout_web/templates/address_contract/index.html.eex:63
msgid "Contract source code"
msgstr ""
@@ -319,7 +319,7 @@ msgid "Copy Txn Hash"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:105
+#: lib/block_scout_web/templates/address/overview.html.eex:107
msgid "Created by"
msgstr ""
@@ -328,14 +328,6 @@ msgstr ""
msgid "Curl"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
-msgid "Data"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@@ -364,19 +356,19 @@ msgid "Error trying to fetch balances."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:148
+#: lib/block_scout_web/views/transaction_view.ex:188
msgid "Error: %{reason}"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:146
+#: lib/block_scout_web/views/transaction_view.ex:186
msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
#, elixir-format
#: 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/layout/app.html.eex:55
+#: lib/block_scout_web/templates/layout/app.html.eex:56
#: 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/overview.html.eex:196
@@ -400,7 +392,7 @@ msgid "Fetching tokens..."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:26
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:40
msgid "Forked Blocks (Reorgs)"
msgstr ""
@@ -454,7 +446,7 @@ msgid "IN"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:51
+#: lib/block_scout_web/templates/layout/app.html.eex:52
msgid "Indexing Tokens"
msgstr ""
@@ -474,7 +466,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:306
-#: lib/block_scout_web/views/transaction_view.ex:274
+#: lib/block_scout_web/views/transaction_view.ex:314
msgid "Internal Transactions"
msgstr ""
@@ -486,7 +478,7 @@ msgid "Inventory"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/app.html.eex:52
+#: lib/block_scout_web/templates/layout/app.html.eex:53
msgid "Less than"
msgstr ""
@@ -501,21 +493,21 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:312
-#: lib/block_scout_web/views/transaction_view.ex:275
+#: lib/block_scout_web/views/transaction_view.ex:315
msgid "Logs"
msgstr ""
#, elixir-format
#: 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:54
#: lib/block_scout_web/views/address_view.ex:121
#: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:129
-#: lib/block_scout_web/views/transaction_view.ex:129
+#: lib/block_scout_web/views/transaction_view.ex:169
+#: lib/block_scout_web/views/transaction_view.ex:169
msgid "Max of"
msgstr ""
@@ -555,9 +547,10 @@ msgid "Must be set to:"
msgstr ""
#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:50
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:52
msgid "Name"
msgstr ""
@@ -604,9 +597,9 @@ msgid "Parent Hash"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:44
-#: lib/block_scout_web/views/transaction_view.ex:143
-#: lib/block_scout_web/views/transaction_view.ex:177
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:58
+#: lib/block_scout_web/views/transaction_view.ex:183
+#: lib/block_scout_web/views/transaction_view.ex:217
msgid "Pending"
msgstr ""
@@ -622,13 +615,13 @@ msgstr ""
#, elixir-format
#: 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:55
msgid "Price"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:33
-#: lib/block_scout_web/templates/address/overview.html.eex:143
+#: lib/block_scout_web/templates/address/overview.html.eex:145
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:36
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106
msgid "QR Code"
@@ -669,8 +662,8 @@ msgstr ""
#, elixir-format
#: 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:119
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:122
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:139
msgid "Search"
msgstr ""
@@ -693,7 +686,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
-#: lib/block_scout_web/views/transaction_view.ex:145
+#: lib/block_scout_web/views/transaction_view.ex:185
msgid "Success"
msgstr ""
@@ -774,7 +767,7 @@ msgid "To"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:6
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation"
msgstr ""
@@ -798,7 +791,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
-#: lib/block_scout_web/views/transaction_view.ex:219
+#: lib/block_scout_web/views/transaction_view.ex:259
msgid "Token Transfer"
msgstr ""
@@ -808,7 +801,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35
-#: lib/block_scout_web/views/transaction_view.ex:273
+#: lib/block_scout_web/views/transaction_view.ex:313
msgid "Token Transfers"
msgstr ""
@@ -825,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
-#, elixir-format
-#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
-msgid "Topics"
-msgstr ""
-
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
@@ -848,7 +835,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:3
-#: lib/block_scout_web/views/transaction_view.ex:222
+#: lib/block_scout_web/views/transaction_view.ex:262
msgid "Transaction"
msgstr ""
@@ -873,7 +860,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: 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:49
#: lib/block_scout_web/views/address_view.ex:305
msgid "Transactions"
msgstr ""
@@ -900,7 +887,7 @@ msgstr ""
#, elixir-format
#: 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:37
msgid "Uncles"
msgstr ""
@@ -915,7 +902,7 @@ msgid "Used"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:39
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:53
msgid "Validated"
msgstr ""
@@ -996,12 +983,12 @@ msgid "Yes"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:111
+#: lib/block_scout_web/templates/address/overview.html.eex:113
msgid "at"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/address_contract_view.ex:22
+#: lib/block_scout_web/views/address_contract_view.ex:23
msgid "false"
msgstr ""
@@ -1019,7 +1006,7 @@ msgid "string"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/address_contract_view.ex:21
+#: lib/block_scout_web/views/address_contract_view.ex:22
msgid "true"
msgstr ""
@@ -1039,14 +1026,7 @@ msgid "Delegate Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/block/_tile.html.eex:47
-#: lib/block_scout_web/templates/chain/_block.html.eex:23
#: lib/block_scout_web/views/internal_transaction_view.ex:27
-msgid "Reward"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct"
msgstr ""
@@ -1058,7 +1038,6 @@ msgstr ""
#, elixir-format
#: 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:125
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:21
msgid "Loading..."
msgstr ""
@@ -1069,22 +1048,17 @@ msgid "Loading...."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:64
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "APIs"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:68
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:82
msgid "GraphQL"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/pending_transaction/index.html.eex:32
-msgid "Loading"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:73
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:87
msgid "RPC"
msgstr ""
@@ -1134,48 +1108,41 @@ msgid "Static Call"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:28
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:34
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:16
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:28
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:36
msgid "Decoded"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
-msgid "Indexed?"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
-msgid "Type"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
msgid "Method Id"
msgstr ""
#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_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."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1
-msgid "Transaction Info"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgid "Transaction Inputs"
msgstr ""
#, 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_log/_logs.html.eex:22
msgid "Verify the contract "
msgstr ""
#, 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_log/_logs.html.eex:22
msgid "here"
@@ -1187,25 +1154,10 @@ msgid "Failed to decode input data."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value"
msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
-msgid "Copy Value"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
-msgid "Failed to decode log data."
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
-msgid "Log Data"
-msgstr ""
+""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
@@ -1277,7 +1229,7 @@ msgid "There are no pending transactions."
msgstr ""
#, 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."
msgstr ""
@@ -1407,17 +1359,17 @@ msgid "Support"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:73
+#: lib/block_scout_web/templates/address_contract/index.html.eex:77
msgid "Copy ABI"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:89
+#: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:61
+#: lib/block_scout_web/templates/address_contract/index.html.eex:65
msgid "Copy Source Code"
msgstr ""
@@ -1432,7 +1384,7 @@ msgid "Contract Libraries"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:88
+#: lib/block_scout_web/templates/address/overview.html.eex:89
msgid "Last Balance Update: Block #"
msgstr ""
@@ -1478,13 +1430,13 @@ msgid "Incoming Transactions"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/overview.html.eex:119
+#: lib/block_scout_web/templates/address/overview.html.eex:121
msgid "Error: Could not determine contract creator."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:96
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:100
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:116
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:120
msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr ""
@@ -1548,7 +1500,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:7
-#: lib/block_scout_web/views/transaction_view.ex:276
+#: lib/block_scout_web/views/transaction_view.ex:316
msgid "Raw Trace"
msgstr ""
@@ -1559,7 +1511,7 @@ msgstr ""
#, elixir-format
#:
-#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:40
+#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:39
msgid "Page"
msgstr ""
@@ -1577,7 +1529,7 @@ msgstr ""
#, elixir-format
#:
-#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:40
+#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:39
msgid "of"
msgstr ""
@@ -1587,27 +1539,27 @@ msgid "Block Details"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:101
+#: lib/block_scout_web/templates/address_contract/index.html.eex:105
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:87
+#: lib/block_scout_web/templates/address_contract/index.html.eex:91
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:93
+#: lib/block_scout_web/templates/address_contract/index.html.eex:97
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:103
+#: lib/block_scout_web/templates/address_contract/index.html.eex:107
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:94
+#: lib/block_scout_web/templates/address_contract/index.html.eex:98
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
@@ -1710,7 +1662,7 @@ msgid "ETH RPC API Documentation"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/layout/_topnav.html.eex:78
+#: lib/block_scout_web/templates/layout/_topnav.html.eex:92
msgid "Eth RPC"
msgstr ""
@@ -1745,8 +1697,8 @@ msgid "here."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_token/index.html.eex:26
-#: lib/block_scout_web/templates/address_transaction/index.html.eex:72
+#: lib/block_scout_web/templates/address_token/index.html.eex:28
+#: lib/block_scout_web/templates/address_transaction/index.html.eex:74
msgid "CSV"
msgstr ""
@@ -1756,22 +1708,17 @@ msgid "Change Network"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:51
-msgid "Constructor arguments"
-msgstr ""
-
-#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:44
+#: lib/block_scout_web/views/transaction_view.ex:84
msgid "ERC-20 "
msgstr ""
#, elixir-format
-#: lib/block_scout_web/views/transaction_view.ex:45
+#: lib/block_scout_web/views/transaction_view.ex:85
msgid "ERC-721 "
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:116
+#: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "External libraries"
msgstr ""
@@ -1804,3 +1751,67 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost"
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_contract/index.html.eex:53
+msgid "Constructor Arguments"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:63
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:65
+msgid "Copy Value"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/views/internal_transaction_view.ex:26
+msgid "Create2"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:53
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:118
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:55
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:121
+msgid "Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:31
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:31
+msgid "Failed to decode log data."
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:52
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:54
+msgid "Indexed?"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
+msgid "Log Data"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/block/_tile.html.eex:47
+#: lib/block_scout_web/templates/chain/_block.html.eex:23
+#: lib/block_scout_web/views/internal_transaction_view.ex:28
+msgid "Reward"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:88
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:91
+msgid "Topics"
+msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_logs/_logs.html.eex:51
+#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
+#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:53
+msgid "Type"
+msgstr ""
diff --git a/apps/block_scout_web/priv/gettext/errors.pot b/apps/block_scout_web/priv/gettext/errors.pot
index ca584666e5..cdaaac6299 100644
--- a/apps/block_scout_web/priv/gettext/errors.pot
+++ b/apps/block_scout_web/priv/gettext/errors.pot
@@ -1,52 +1,52 @@
-## This file is a PO Template file.
-##
-## `msgid`s here are often extracted from source code.
-## Add new translations manually only if they're dynamic
-## translations that can't be statically extracted.
-##
-## Run `mix gettext.extract` to bring this file up to
-## date. Leave `msgstr`s empty as changing them here as no
-## effect: edit them in PO (`.po`) files instead.
-## From Ecto.Changeset.cast/4
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""
-## From Ecto.Changeset.unique_constraint/3
+## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""
-## From Ecto.Changeset.put_change/3
+## From Ecto.Changeset.put_change/3
msgid "is invalid"
msgstr ""
-## From Ecto.Changeset.validate_acceptance/3
+## From Ecto.Changeset.validate_acceptance/3
msgid "must be accepted"
msgstr ""
-## From Ecto.Changeset.validate_format/3
+## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""
-## From Ecto.Changeset.validate_subset/3
+## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
msgstr ""
-## From Ecto.Changeset.validate_exclusion/3
+## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""
-## From Ecto.Changeset.validate_confirmation/3
+## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
msgstr ""
-## From Ecto.Changeset.no_assoc_constraint/3
+## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry"
msgstr ""
msgid "are still associated with this entry"
msgstr ""
-## From Ecto.Changeset.validate_length/3
+## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
@@ -77,7 +77,7 @@ msgid_plural "should have at most %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
-## From Ecto.Changeset.validate_number/3
+## From Ecto.Changeset.validate_number/3
msgid "must be less than %{number}"
msgstr ""
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
index a29d6b9be6..63a27c7f7b 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
@@ -13,10 +13,16 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
assert html_response(conn, 422)
end
- test "with valid address hash without address", %{conn: conn} do
- conn = get(conn, address_transaction_path(conn, :index, "0x8bf38d4764929064f2d4d3a56520a76ab3df415b"))
+ test "with valid address hash without address in the DB", %{conn: conn} do
+ conn =
+ get(
+ conn,
+ address_transaction_path(conn, :index, "0x8bf38d4764929064f2d4d3a56520a76ab3df415b", %{"type" => "JSON"})
+ )
- assert html_response(conn, 404)
+ assert json_response(conn, 200)
+ transaction_tiles = json_response(conn, 200)["items"]
+ assert transaction_tiles |> length() == 0
end
test "returns transactions for the address", %{conn: conn} do
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/eth_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/eth_controller_test.exs
index 1b9273c66c..4b43909ac4 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/eth_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/eth_controller_test.exs
@@ -125,6 +125,57 @@ defmodule BlockScoutWeb.API.RPC.EthControllerTest do
assert [%{"data" => "0x010101"}, %{"data" => "0x020202"}] = Enum.sort_by(response["result"], &Map.get(&1, "data"))
end
+ test "paginates logs", %{conn: conn, api_params: api_params} do
+ contract_address = insert(:contract_address)
+
+ transaction =
+ :transaction
+ |> insert(to_address: contract_address)
+ |> with_block()
+
+ inserted_records =
+ insert_list(2000, :log, address: contract_address, transaction: transaction, first_topic: "0x01")
+
+ params = params(api_params, [%{"address" => to_string(contract_address), "topics" => [["0x01"]]}])
+
+ assert response =
+ conn
+ |> post("/api/eth_rpc", params)
+ |> json_response(200)
+
+ assert Enum.count(response["result"]) == 1000
+
+ {last_log_index, ""} = Integer.parse(List.last(response["result"])["logIndex"], 16)
+
+ next_page_params = %{
+ "blockNumber" => Integer.to_string(transaction.block_number, 16),
+ "transactionIndex" => transaction.index,
+ "logIndex" => Integer.to_string(last_log_index, 16)
+ }
+
+ new_params =
+ params(api_params, [
+ %{"paging_options" => next_page_params, "address" => to_string(contract_address), "topics" => [["0x01"]]}
+ ])
+
+ assert new_response =
+ conn
+ |> post("/api/eth_rpc", new_params)
+ |> json_response(200)
+
+ assert Enum.count(response["result"]) == 1000
+
+ all_found_logs = response["result"] ++ new_response["result"]
+
+ assert Enum.all?(inserted_records, fn record ->
+ Enum.any?(all_found_logs, fn found_log ->
+ {index, ""} = Integer.parse(found_log["logIndex"], 16)
+
+ record.index == index
+ end)
+ end)
+ end
+
test "with a matching address and multiple topic matches in different positions", %{
conn: conn,
api_params: api_params
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
index 41735f685a..19631ff746 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
@@ -1,6 +1,15 @@
defmodule BlockScoutWeb.API.V1.HealthControllerTest do
use BlockScoutWeb.ConnCase
+ alias Explorer.{Chain, PagingOptions}
+
+ setup do
+ Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
+ Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
+
+ :ok
+ end
+
describe "GET last_block_status/0" do
test "returns error when there are no blocks in db", %{conn: conn} do
request = get(conn, api_v1_health_path(conn, :health))
@@ -32,19 +41,50 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do
end
test "returns ok when last block is not stale", %{conn: conn} do
- insert(:block, consensus: true, timestamp: DateTime.utc_now())
+ block1 = insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 2)
+ insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
request = get(conn, api_v1_health_path(conn, :health))
assert request.status == 200
+ result = Poison.decode!(request.resp_body)
+
+ assert result["healthy"] == true
+
assert %{
- "healthy" => true,
- "data" => %{
- "latest_block_number" => _,
- "latest_block_inserted_at" => _
- }
- } = Poison.decode!(request.resp_body)
+ "latest_block_number" => to_string(block1.number),
+ "latest_block_inserted_at" => to_string(block1.timestamp),
+ "cache_latest_block_number" => to_string(block1.number),
+ "cache_latest_block_inserted_at" => to_string(block1.timestamp)
+ } == result["data"]
end
end
+
+ test "return error when cache is stale", %{conn: conn} do
+ stale_block = insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50), number: 3)
+ state_block_hash = stale_block.hash
+
+ assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
+
+ insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
+
+ assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
+
+ request = get(conn, api_v1_health_path(conn, :health))
+
+ assert request.status == 500
+
+ assert %{
+ "healthy" => false,
+ "error_code" => 5001,
+ "error_title" => "blocks fetching is stuck",
+ "error_description" =>
+ "There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance",
+ "data" => %{
+ "latest_block_number" => _,
+ "latest_block_inserted_at" => _
+ }
+ } = Poison.decode!(request.resp_body)
+ end
end
diff --git a/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
index 2a3e5492ed..69cca69f41 100644
--- a/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
@@ -253,4 +253,34 @@ defmodule BlockScoutWeb.TransactionViewTest do
assert TransactionView.current_tab_name(logs_path) == "Logs"
end
end
+
+ describe "aggregate_token_transfers/1" do
+ test "aggregates token transfers" do
+ transaction =
+ :transaction
+ |> insert()
+ |> with_block()
+
+ token_transfer = insert(:token_transfer, transaction: transaction, amount: Decimal.new(1))
+
+ result = TransactionView.aggregate_token_transfers([token_transfer, token_transfer, token_transfer])
+
+ assert Enum.count(result) == 1
+ assert List.first(result).amount == Decimal.new(3)
+ end
+
+ test "does not aggregate NFT tokens" do
+ transaction =
+ :transaction
+ |> insert()
+ |> with_block()
+
+ token_transfer = insert(:token_transfer, transaction: transaction, amount: nil)
+
+ result = TransactionView.aggregate_token_transfers([token_transfer, token_transfer, token_transfer])
+
+ assert Enum.count(result) == 3
+ assert List.first(result).amount == nil
+ end
+ end
end
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
index ab725c9c73..e0a6672be8 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
@@ -5,7 +5,7 @@ defmodule EthereumJSONRPC.Geth do
import EthereumJSONRPC, only: [id_to_params: 1, integer_to_quantity: 1, json_rpc: 2, request: 1]
- alias EthereumJSONRPC.{FetchedBalance, FetchedCode}
+ alias EthereumJSONRPC.{FetchedBalance, FetchedCode, Transactions}
alias EthereumJSONRPC.Geth.{Calls, Tracer}
@behaviour EthereumJSONRPC.Variant
@@ -46,12 +46,31 @@ defmodule EthereumJSONRPC.Geth do
def fetch_block_internal_transactions(_block_range, _json_rpc_named_arguments), do: :ignore
@doc """
- Pending transaction fetching is not supported currently for Geth.
-
- To signal to the caller that fetching is not supported, `:ignore` is returned.
+ Fetches the pending transactions from the Geth node.
"""
@impl EthereumJSONRPC.Variant
- def fetch_pending_transactions(_json_rpc_named_arguments), do: :ignore
+ def fetch_pending_transactions(json_rpc_named_arguments) do
+ with {:ok, transaction_data} <-
+ %{id: 1, method: "txpool_content", params: []} |> request() |> json_rpc(json_rpc_named_arguments) do
+ transactions_params =
+ transaction_data["pending"]
+ |> Enum.flat_map(fn {_address, nonce_transactions_map} ->
+ nonce_transactions_map
+ |> Enum.map(fn {_nonce, transaction} ->
+ transaction
+ end)
+ end)
+ |> Transactions.to_elixir()
+ |> Transactions.elixir_to_params()
+ |> Enum.map(fn params ->
+ # txpool_content always returns transaction with 0x0000000000000000000000000000000000000000000000000000000000000000 value in block hash and index is null.
+ # https://github.com/ethereum/go-ethereum/issues/19897
+ %{params | block_hash: nil, index: nil}
+ end)
+
+ {:ok, transactions_params}
+ end
+ end
defp debug_trace_transaction_requests(id_to_params) when is_map(id_to_params) do
Enum.map(id_to_params, fn {id, %{hash_data: hash_data}} ->
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
index 1555ea6c8f..c83b157324 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
@@ -426,13 +426,14 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash,
"index" => index,
"traceAddress" => trace_address,
- "type" => "create" = type,
+ "type" => type,
"from" => from_address_hash,
"error" => error,
"gas" => gas,
"init" => init,
"value" => value
- }) do
+ })
+ when type in ~w(create create2) do
%{
block_number: block_number,
transaction_index: transaction_index,
@@ -454,7 +455,7 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash,
"index" => index,
"traceAddress" => trace_address,
- "type" => "create",
+ "type" => type,
"from" => from_address_hash,
"createdContractAddressHash" => created_contract_address_hash,
"gas" => gas,
@@ -462,14 +463,15 @@ defmodule EthereumJSONRPC.Geth.Call do
"init" => init,
"createdContractCode" => created_contract_code,
"value" => value
- }) do
+ })
+ when type in ~w(create create2) do
%{
block_number: block_number,
transaction_index: transaction_index,
transaction_hash: transaction_hash,
index: index,
trace_address: trace_address,
- type: "create",
+ type: type,
from_address_hash: from_address_hash,
gas: gas,
gas_used: gas_used,
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
index 6545250b4a..cbc43fa71d 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
@@ -113,6 +113,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
end
defp op(%{"op" => "CREATE"} = log, ctx), do: create_op(log, ctx)
+ defp op(%{"op" => "CREATE2"} = log, ctx), do: create_op(log, ctx, "create2")
defp op(%{"op" => "SELFDESTRUCT"} = log, ctx), do: self_destruct_op(log, ctx)
defp op(%{"op" => "CALL"} = log, ctx), do: call_op(log, "call", ctx)
defp op(%{"op" => "CALLCODE"} = log, ctx), do: call_op(log, "callcode", ctx)
@@ -155,7 +156,8 @@ defmodule EthereumJSONRPC.Geth.Tracer do
defp create_op(
%{"stack" => log_stack, "memory" => log_memory},
- %{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx
+ %{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx,
+ type \\ "create"
) do
[value, input_offset, input_length | _] = Enum.reverse(log_stack)
@@ -165,7 +167,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
|> String.slice(quantity_to_integer("0x" <> input_offset) * 2, quantity_to_integer("0x" <> input_length) * 2)
call = %{
- "type" => "create",
+ "type" => type,
"from" => nil,
"traceAddress" => Enum.reverse(trace_address),
"init" => "0x" <> init,
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex
index f021bfa153..7992c0e63c 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex
@@ -353,4 +353,8 @@ defmodule EthereumJSONRPC.Transaction do
_ -> {key, quantity_to_integer(chain_id)}
end
end
+
+ defp entry_to_elixir(_) do
+ {nil, nil}
+ end
end
diff --git a/apps/ethereum_jsonrpc/mix.exs b/apps/ethereum_jsonrpc/mix.exs
index 7c2299c4a8..e3949457e9 100644
--- a/apps/ethereum_jsonrpc/mix.exs
+++ b/apps/ethereum_jsonrpc/mix.exs
@@ -64,7 +64,7 @@ defmodule EthereumJsonrpc.MixProject do
# WebSocket-server for testing `EthereumJSONRPC.WebSocket.WebSocketClient`.
{:cowboy, "~> 2.0", only: [:dev, :test]},
# Style Checking
- {:credo, "1.0.0", only: :test, runtime: false},
+ {:credo, "~> 1.1", only: :test, runtime: false},
# Static Type Checking
{:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false},
# Code coverage
@@ -82,7 +82,7 @@ defmodule EthereumJsonrpc.MixProject do
# `:spandex` integration with Datadog
{:spandex_datadog, "~> 0.4.0"},
# Convert unix timestamps in JSONRPC to DateTimes
- {:timex, "~> 3.4"},
+ {:timex, "~> 3.6"},
# Encode/decode function names and arguments
{:ex_abi, "~> 0.1.18"},
# `:verify_fun` for `Socket.Web.connect`
diff --git a/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js b/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
index 15db7d8ff9..5c3c98f871 100644
--- a/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
+++ b/apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
@@ -91,6 +91,9 @@
case 'CREATE':
this.createOp(log);
break;
+ case 'CREATE2':
+ this.create2Op(log);
+ break;
case 'SELFDESTRUCT':
this.selfDestructOp(log, db);
break;
@@ -127,7 +130,7 @@
const ret = log.stack.peek(0);
if (!ret.equals(0)) {
- if (call.type === 'create') {
+ if (call.type === 'create' || call.type === 'create2') {
call.createdContractAddressHash = toHex(toAddress(ret.toString(16)));
call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16))));
} else {
@@ -162,6 +165,21 @@
this.callStack.push(call);
},
+ create2Op(log) {
+ const inputOffset = log.stack.peek(1).valueOf();
+ const inputLength = log.stack.peek(2).valueOf();
+ const inputEnd = inputOffset + inputLength;
+ const stackValue = log.stack.peek(0);
+
+ const call = {
+ type: 'create2',
+ from: toHex(log.contract.getAddress()),
+ init: toHex(log.memory.slice(inputOffset, inputEnd)),
+ valueBigInt: bigInt(stackValue.toString(10))
+ };
+ this.callStack.push(call);
+ },
+
selfDestructOp(log, db) {
const contractAddress = log.contract.getAddress();
@@ -243,6 +261,9 @@
case 'CREATE':
result = this.ctxToCreate(ctx, db);
break;
+ case 'CREATE2':
+ result = this.ctxToCreate2(ctx, db);
+ break;
}
return result;
@@ -292,6 +313,22 @@
return result;
},
+ ctxToCreate2(ctx, db) {
+ const result = {
+ type: 'create2',
+ from: toHex(ctx.from),
+ init: toHex(ctx.input),
+ valueBigInt: bigInt(ctx.value.toString(10)),
+ gasBigInt: bigInt(ctx.gas),
+ gasUsedBigInt: bigInt(ctx.gasUsed)
+ };
+
+ this.putBottomChildCalls(result);
+ this.putErrorOrCreatedContract(result, ctx, db);
+
+ return result;
+ },
+
putBottomChildCalls(result) {
const bottomCall = this.bottomCall();
const bottomChildCalls = bottomCall.calls;
@@ -422,4 +459,3 @@
call.gasUsed = '0x' + gasUsedBigInt.toString(16);
}
}
-
diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs
index 626583fa01..32a7f84df6 100644
--- a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs
+++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs
@@ -84,8 +84,133 @@ defmodule EthereumJSONRPC.GethTest do
end
describe "fetch_pending_transactions/1" do
- test "is not supported", %{json_rpc_named_arguments: json_rpc_named_arguments} do
- EthereumJSONRPC.Geth.fetch_pending_transactions(json_rpc_named_arguments)
+ @tag :no_geth
+ test "fetches pending transactions", %{json_rpc_named_arguments: json_rpc_named_arguments} do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn _, _ ->
+ {:ok,
+ %{
+ "pending" => %{
+ "0xC99f4e9cFf697ca6717ad9cE8bA4A138e0e55109" => %{
+ "4656" => %{
+ "blockHash" => "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber" => nil,
+ "from" => "0xc99f4e9cff697ca6717ad9ce8ba4a138e0e55109",
+ "gas" => "0x3d0900",
+ "gasPrice" => "0x3b9aca00",
+ "hash" => "0x2b8cfd76a31b942e51b6265c791c860e2840b11f8c2fcfa1c9dfe53dea4c3102",
+ "input" =>
+ "0xc47e300d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000030af6932dec7c4eaf4b966059e74cc7a1767ba93e62f2d83a7dba5bb785b6efd25e8ab7d2e8798e7ecc27df96380d77a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000b29e5229b86fbb3a8e45e406b64226c3d49389804a6f7449325fae232d6623000000000000000000000000000000000000000000000000000000000000006097e4c1ed443f430b1d8ad66e565a960fade76e3e177b4120186bdad2fcfa43e134de3abdc0272c9433af94833fec73260c261cf41422e83d958787b62144478bc44ab84d1ddba7a462d355057f3be8ab914a195ac1a637c4fb8503c441dadb45",
+ "nonce" => "0x1230",
+ "r" => "0x81345ae149171f4cb4ab868f0ad637d033c96c4659b190b86a39725c8299c947",
+ "s" => "0x31450678841d7206fa02b564a641420262cc98c8ea0e32c4cb0e97208d3f9feb",
+ "to" => "0xf003a84d6890202663c0fd80954e836fcf21e004",
+ "transactionIndex" => "0x0",
+ "v" => "0x1b",
+ "value" => "0xb5e620f480000"
+ },
+ "4657" => %{
+ "blockHash" => "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber" => nil,
+ "from" => "0xc99f4e9cff697ca6717ad9ce8ba4a138e0e55109",
+ "gas" => "0x3d0900",
+ "gasPrice" => "0x3b9aca00",
+ "hash" => "0x7c3ea924740e996bf552a8dded903ba4258b69d30bf5e6dca6ec86ebc60b8151",
+ "input" =>
+ "0xc47e300d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000030a25723bca32f88a73abc7eb153cee248effd563d87efe12e08e8a33f74047afc28c30ab9c74bddeb6f0558628b8bf200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020009c56025b2796cdc72f91836278a471590b774462adddd1c87a0b6f84b787990000000000000000000000000000000000000000000000000000000000000060aa53b46c8b57aed7c4c0fdf3f650ec3bb330591929bc813610656882e3203157c22b50d0d0b0316a8712c00fe4f0e0c509613114f5d24c0419a4e8188f2489678b05dccf72a67957785e8e250092c8787f049f7e20b1414a633595a56c98ff82",
+ "nonce" => "0x1231",
+ "r" => "0xee1eb895262d12ef5c4ee3cbf9b36de3903bc3a1343f0a312bd19edacc4bb877",
+ "s" => "0xfcb87efe4c3984a3e1d3f4fb10ce41e59f65e21fbd9206a1648ec73fa0a2206",
+ "to" => "0xf003a84d6890202663c0fd80954e836fcf21e004",
+ "transactionIndex" => "0x0",
+ "v" => "0x1b",
+ "value" => "0xb5e620f480000"
+ },
+ "4658" => %{
+ "blockHash" => "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber" => nil,
+ "from" => "0xc99f4e9cff697ca6717ad9ce8ba4a138e0e55109",
+ "gas" => "0x3d0900",
+ "gasPrice" => "0x3b9aca00",
+ "hash" => "0xe699a58ef4986f2dbdc102acf73b35392aff9ce43fd226000526955e19c0b06e",
+ "input" =>
+ "0xc47e300d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000308eb3ed9e686f6bc1fe2d8ce3fea37fb3a66a9c67b91ef15ba6bd7da0eed73288f72577edea2b7ded5855ca8a56b1e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000051afe6c51e2175a62afbd66d293e8a7509943d5cd6f851f59923a61a186e80000000000000000000000000000000000000000000000000000000000000060a063498e8db2e75e0a193de89ad2947111d677c9501e75c34a64fcee8fe5a7c7607929fc6bce943d64f1039e1d1f325f02d1e5d71f86ca976c9ab79d19f0fd0e530a5210fbe131087ba1f1b3c92abc4a0dd7c8a47c3c276fac3e09bca964fd74",
+ "nonce" => "0x1232",
+ "r" => "0xe95bc86fc32cc591677c7ec9ca49f1dc33a31427235c1c41dbb7a3a957b55599",
+ "s" => "0xe8b41a6440d0fe6d0ec1f40982394a2d641b19b983aad49e45614e5f3a1abc9",
+ "to" => "0xf003a84d6890202663c0fd80954e836fcf21e004",
+ "transactionIndex" => "0x0",
+ "v" => "0x1c",
+ "value" => "0xb5e620f480000"
+ }
+ }
+ },
+ "queued" => %{}
+ }}
+ end)
+
+ assert {:ok,
+ [
+ %{
+ block_hash: nil,
+ block_number: nil,
+ from_address_hash: "0xc99f4e9cff697ca6717ad9ce8ba4a138e0e55109",
+ gas: 4_000_000,
+ gas_price: 1_000_000_000,
+ hash: "0x2b8cfd76a31b942e51b6265c791c860e2840b11f8c2fcfa1c9dfe53dea4c3102",
+ index: 0,
+ input:
+ "0xc47e300d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000030af6932dec7c4eaf4b966059e74cc7a1767ba93e62f2d83a7dba5bb785b6efd25e8ab7d2e8798e7ecc27df96380d77a0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000b29e5229b86fbb3a8e45e406b64226c3d49389804a6f7449325fae232d6623000000000000000000000000000000000000000000000000000000000000006097e4c1ed443f430b1d8ad66e565a960fade76e3e177b4120186bdad2fcfa43e134de3abdc0272c9433af94833fec73260c261cf41422e83d958787b62144478bc44ab84d1ddba7a462d355057f3be8ab914a195ac1a637c4fb8503c441dadb45",
+ nonce: 4656,
+ r:
+ 58_440_860_745_466_360_584_510_362_592_650_991_653_332_571_230_597_223_185_413_246_840_900_756_818_247,
+ s:
+ 22_285_286_687_634_777_993_513_656_263_235_057_426_117_768_584_265_280_722_872_863_042_386_096_267_243,
+ to_address_hash: "0xf003a84d6890202663c0fd80954e836fcf21e004",
+ transaction_index: 0,
+ v: 27,
+ value: 3_200_000_000_000_000
+ },
+ %{
+ block_hash: nil,
+ block_number: nil,
+ from_address_hash: "0xc99f4e9cff697ca6717ad9ce8ba4a138e0e55109",
+ gas: 4_000_000,
+ gas_price: 1_000_000_000,
+ hash: "0x7c3ea924740e996bf552a8dded903ba4258b69d30bf5e6dca6ec86ebc60b8151",
+ index: 0,
+ input:
+ "0xc47e300d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000030a25723bca32f88a73abc7eb153cee248effd563d87efe12e08e8a33f74047afc28c30ab9c74bddeb6f0558628b8bf200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020009c56025b2796cdc72f91836278a471590b774462adddd1c87a0b6f84b787990000000000000000000000000000000000000000000000000000000000000060aa53b46c8b57aed7c4c0fdf3f650ec3bb330591929bc813610656882e3203157c22b50d0d0b0316a8712c00fe4f0e0c509613114f5d24c0419a4e8188f2489678b05dccf72a67957785e8e250092c8787f049f7e20b1414a633595a56c98ff82",
+ nonce: 4657,
+ r:
+ 107_704_737_317_141_024_268_971_404_113_297_355_261_066_880_504_936_960_891_977_784_149_226_505_877_623,
+ s:
+ 7_144_300_886_174_743_587_831_226_472_052_852_957_529_607_874_128_062_849_708_955_356_153_894_281_734,
+ to_address_hash: "0xf003a84d6890202663c0fd80954e836fcf21e004",
+ transaction_index: 0,
+ v: 27,
+ value: 3_200_000_000_000_000
+ },
+ %{
+ block_hash: nil,
+ block_number: nil,
+ from_address_hash: "0xc99f4e9cff697ca6717ad9ce8ba4a138e0e55109",
+ gas: 4_000_000,
+ gas_price: 1_000_000_000,
+ hash: "0xe699a58ef4986f2dbdc102acf73b35392aff9ce43fd226000526955e19c0b06e",
+ index: 0,
+ input:
+ "0xc47e300d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000308eb3ed9e686f6bc1fe2d8ce3fea37fb3a66a9c67b91ef15ba6bd7da0eed73288f72577edea2b7ded5855ca8a56b1e01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000051afe6c51e2175a62afbd66d293e8a7509943d5cd6f851f59923a61a186e80000000000000000000000000000000000000000000000000000000000000060a063498e8db2e75e0a193de89ad2947111d677c9501e75c34a64fcee8fe5a7c7607929fc6bce943d64f1039e1d1f325f02d1e5d71f86ca976c9ab79d19f0fd0e530a5210fbe131087ba1f1b3c92abc4a0dd7c8a47c3c276fac3e09bca964fd74",
+ nonce: 4658,
+ r:
+ 105_551_060_165_173_654_536_466_245_809_705_255_348_773_503_447_188_823_324_699_103_004_494_755_354_009,
+ s:
+ 6_578_424_718_200_222_268_891_012_570_118_685_130_111_416_504_340_507_122_286_266_818_507_627_932_617,
+ to_address_hash: "0xf003a84d6890202663c0fd80954e836fcf21e004",
+ transaction_index: 0,
+ v: 28,
+ value: 3_200_000_000_000_000
+ }
+ ]} = Geth.fetch_pending_transactions(json_rpc_named_arguments)
end
end
end
diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/transaction_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/transaction_test.exs
index ad7780181d..a8a8fcdfd2 100644
--- a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/transaction_test.exs
+++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/transaction_test.exs
@@ -2,4 +2,14 @@ defmodule EthereumJSONRPC.TransactionTest do
use ExUnit.Case, async: true
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
diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs
index defd5ae9e5..fed5124a2a 100644
--- a/apps/explorer/config/config.exs
+++ b/apps/explorer/config/config.exs
@@ -17,7 +17,15 @@ config :explorer,
if(System.get_env("UNCLES_IN_AVERAGE_BLOCK_TIME") == "false", do: false, else: true),
healthy_blocks_period: System.get_env("HEALTHY_BLOCKS_PERIOD") || :timer.minutes(5)
-config :explorer, Explorer.Counters.AverageBlockTime, enabled: true
+average_block_period =
+ case Integer.parse(System.get_env("AVERAGE_BLOCK_CACHE_PERIOD", "")) do
+ {secs, ""} -> :timer.seconds(secs)
+ _ -> :timer.minutes(30)
+ end
+
+config :explorer, Explorer.Counters.AverageBlockTime,
+ enabled: true,
+ period: average_block_period
config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true
@@ -106,6 +114,14 @@ config :spandex_ecto, SpandexEcto.EctoLogger,
tracer: Explorer.Tracer,
otp_app: :explorer
+market_history_cache_period =
+ case Integer.parse(System.get_env("MARKET_HISTORY_CACHE_PERIOD", "")) do
+ {secs, ""} -> :timer.seconds(secs)
+ _ -> :timer.hours(6)
+ end
+
+config :explorer, Explorer.Market.MarketHistoryCache, period: market_history_cache_period
+
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index 17116658bf..e6ffcbd9c5 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -232,7 +232,7 @@ defmodule Explorer.Chain do
address_hash
|> address_to_transactions_without_rewards(paging_options, options)
- |> Enum.concat(Task.await(rewards_task))
+ |> Enum.concat(Task.await(rewards_task, :timer.seconds(20)))
|> Enum.sort_by(fn item ->
case item do
{%Reward{} = emission_reward, _} ->
@@ -273,7 +273,7 @@ defmodule Explorer.Chain do
from(log in Log,
inner_join: transaction in assoc(log, :transaction),
order_by: [desc: transaction.block_number, desc: transaction.index],
- preload: [:transaction],
+ preload: [:transaction, transaction: [to_address: :smart_contract]],
where: transaction.block_number < ^block_number,
or_where: transaction.block_number == ^block_number and transaction.index > ^transaction_index,
or_where:
@@ -364,8 +364,8 @@ defmodule Explorer.Chain do
Uncles are not currently accounted for.
"""
- @spec block_reward(Block.t()) :: Wei.t()
- def block_reward(%Block{number: block_number}) do
+ @spec block_reward(Block.block_number()) :: Wei.t()
+ def block_reward(block_number) do
query =
from(
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
the `index` that are passed.
"""
- @spec block_to_transactions(Block.t(), [paging_options | necessity_by_association_option]) :: [Transaction.t()]
- def block_to_transactions(%Block{hash: block_hash}, options \\ []) when is_list(options) do
+ @spec block_to_transactions(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [Transaction.t()]
+ def block_to_transactions(block_hash, options \\ []) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
options
@@ -432,8 +432,8 @@ defmodule Explorer.Chain do
@doc """
Counts the number of `t:Explorer.Chain.Transaction.t/0` in the `block`.
"""
- @spec block_to_transaction_count(Block.t()) :: non_neg_integer()
- def block_to_transaction_count(%Block{hash: block_hash}) do
+ @spec block_to_transaction_count(Hash.Full.t()) :: non_neg_integer()
+ def block_to_transaction_count(block_hash) do
query =
from(
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, :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}
def get_balance_as_of_block(address, block) when is_integer(block) do
coin_balance_query =
@@ -930,33 +930,44 @@ defmodule Explorer.Chain do
Repo.all(query)
end
- @spec find_contract_address(Hash.t()) :: {:ok, Address.t()} | {:error, :not_found}
- def find_contract_address(%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash) do
+ @doc """
+ 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 =
from(
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)
)
- query_with_decompiled_flag = with_decompiled_code_flag(query, hash)
-
- address = Repo.one(query_with_decompiled_flag)
-
- if address do
- {:ok, address}
- else
- {:error, :not_found}
+ query
+ |> join_associations(necessity_by_association)
+ |> with_decompiled_code_flag(hash, query_decompiled_code_flag)
+ |> Repo.one()
+ |> case do
+ nil -> {:error, :not_found}
+ address -> {:ok, address}
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
query =
from(
@@ -1807,7 +1818,7 @@ defmodule Explorer.Chain do
Repo.one!(query)
end
- def last_block_status do
+ def last_db_block_status do
query =
from(block in Block,
select: {block.number, block.timestamp},
@@ -1816,22 +1827,39 @@ defmodule Explorer.Chain do
limit: 1
)
- case Repo.one(query) do
- nil ->
- {:error, :no_blocks}
+ query
+ |> Repo.one()
+ |> block_status()
+ end
- {number, timestamp} ->
- now = DateTime.utc_now()
- last_block_period = DateTime.diff(now, timestamp, :millisecond)
+ def last_cache_block_status do
+ [
+ paging_options: %PagingOptions{page_size: 1}
+ ]
+ |> list_blocks()
+ |> List.last()
+ |> case do
+ %{timestamp: timestamp, number: number} ->
+ block_status({number, timestamp})
- if last_block_period > Application.get_env(:explorer, :healthy_blocks_period) do
- {:error, number, timestamp}
- else
- {:ok, number, timestamp}
- end
+ _ ->
+ block_status(nil)
end
end
+ defp block_status({number, timestamp}) do
+ now = DateTime.utc_now()
+ last_block_period = DateTime.diff(now, timestamp, :millisecond)
+
+ if last_block_period > Application.get_env(:explorer, :healthy_blocks_period) do
+ {:error, number, timestamp}
+ else
+ {:ok, number, timestamp}
+ end
+ end
+
+ defp block_status(nil), do: {:error, :no_blocks}
+
@doc """
Calculates the ranges of missing consensus blocks in `range`.
@@ -2209,14 +2237,10 @@ defmodule Explorer.Chain do
"""
- @spec transaction_to_internal_transactions(Transaction.t(), [paging_options | necessity_by_association_option]) :: [
+ @spec transaction_to_internal_transactions(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [
InternalTransaction.t()
]
- def transaction_to_internal_transactions(
- %Transaction{hash: %Hash{byte_count: unquote(Hash.Full.byte_count())} = hash},
- options \\ []
- )
- when is_list(options) do
+ def transaction_to_internal_transactions(hash, options \\ []) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@@ -2244,12 +2268,8 @@ defmodule Explorer.Chain do
the `index` that are passed.
"""
- @spec transaction_to_logs(Transaction.t(), [paging_options | necessity_by_association_option]) :: [Log.t()]
- def transaction_to_logs(
- %Transaction{hash: %Hash{byte_count: unquote(Hash.Full.byte_count())} = transaction_hash},
- options \\ []
- )
- when is_list(options) do
+ @spec transaction_to_logs(Hash.Full.t(), [paging_options | necessity_by_association_option]) :: [Log.t()]
+ def transaction_to_logs(transaction_hash, options \\ []) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@@ -2276,14 +2296,10 @@ defmodule Explorer.Chain do
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()
]
- def transaction_to_token_transfers(
- %Transaction{hash: %Hash{byte_count: unquote(Hash.Full.byte_count())} = transaction_hash},
- options \\ []
- )
- when is_list(options) do
+ def transaction_to_token_transfers(transaction_hash, options \\ []) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@@ -2448,9 +2464,10 @@ defmodule Explorer.Chain do
|> Multi.run(:set_address_verified, &set_address_verified/2)
|> Repo.transaction()
- with {:ok, %{smart_contract: smart_contract}} <- insert_result do
- {:ok, smart_contract}
- else
+ case insert_result do
+ {:ok, %{smart_contract: smart_contract}} ->
+ {:ok, smart_contract}
+
{:error, :smart_contract, changeset, _} ->
{:error, changeset}
@@ -2510,16 +2527,16 @@ defmodule Explorer.Chain do
|> repo.insert(on_conflict: :nothing, conflict_target: [:address_hash, :name])
end
- @spec address_hash_to_address_with_source_code(%Explorer.Chain.Hash{}) :: %Explorer.Chain.Address{} | nil
- def address_hash_to_address_with_source_code(%Explorer.Chain.Hash{} = address_hash) do
+ @spec address_hash_to_address_with_source_code(Hash.Address.t()) :: Address.t() | nil
+ def address_hash_to_address_with_source_code(address_hash) do
case Repo.get(Address, address_hash) do
nil -> nil
address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts])
end
end
- @spec address_hash_to_smart_contract(%Explorer.Chain.Hash{}) :: %Explorer.Chain.SmartContract{} | nil
- def address_hash_to_smart_contract(%Explorer.Chain.Hash{} = address_hash) do
+ @spec address_hash_to_smart_contract(Hash.Address.t()) :: SmartContract.t() | nil
+ def address_hash_to_smart_contract(address_hash) do
query =
from(
smart_contract in SmartContract,
@@ -2585,7 +2602,11 @@ defmodule Explorer.Chain do
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)
+ from(address in query,
+ where:
+ (address.fetched_coin_balance == ^coin_balance and address.hash > ^hash) or
+ address.fetched_coin_balance < ^coin_balance
+ )
end
defp page_blocks(query, %PagingOptions{key: nil}), do: query
@@ -2920,9 +2941,10 @@ defmodule Explorer.Chain do
)
|> Repo.transaction()
- with {:ok, %{token: token}} <- insert_result do
- {:ok, token}
- else
+ case insert_result do
+ {:ok, %{token: token}} ->
+ {:ok, token}
+
{:error, :token, changeset, _} ->
{:error, changeset}
end
@@ -3276,8 +3298,6 @@ defmodule Explorer.Chain do
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, true) do
@@ -3300,4 +3320,203 @@ defmodule Explorer.Chain do
|> Base.decode16!(case: :mixed)
|> TypeDecoder.decode_raw(types)
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
diff --git a/apps/explorer/lib/explorer/chain/hash/address.ex b/apps/explorer/lib/explorer/chain/hash/address.ex
index fefdf8743c..4cb1ba751f 100644
--- a/apps/explorer/lib/explorer/chain/hash/address.ex
+++ b/apps/explorer/lib/explorer/chain/hash/address.ex
@@ -166,7 +166,7 @@ defmodule Explorer.Chain.Hash.Address do
iex> Explorer.Chain.Hash.Address.validate("0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232H")
{:error, :invalid_characters}
"""
- @spec validate(String.t()) :: {:ok, String.t()} | {:error, :invalid_length | :invalid_characters, :invalid_checksum}
+ @spec validate(String.t()) :: {:ok, String.t()} | {:error, :invalid_length | :invalid_characters | :invalid_checksum}
def validate("0x" <> hash) do
with {:length, true} <- {:length, String.length(hash) == 40},
{:hex, true} <- {:hex, is_hex?(hash)},
diff --git a/apps/explorer/lib/explorer/chain/import/runner/internal_transactions.ex b/apps/explorer/lib/explorer/chain/import/runner/internal_transactions.ex
index 5e2e4e32f5..50529e8ce8 100644
--- a/apps/explorer/lib/explorer/chain/import/runner/internal_transactions.ex
+++ b/apps/explorer/lib/explorer/chain/import/runner/internal_transactions.ex
@@ -73,10 +73,12 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactions do
# order so that row ShareLocks are grabbed in a consistent order
ordered_changes_list = Enum.sort_by(changes_list, &{&1.transaction_hash, &1.index})
+ final_changes_list = reject_pending_transactions(ordered_changes_list, repo)
+
{:ok, internal_transactions} =
Import.insert_changes_list(
repo,
- ordered_changes_list,
+ final_changes_list,
conflict_target: [:transaction_hash, :index],
for: InternalTransaction,
on_conflict: on_conflict,
@@ -156,6 +158,7 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactions do
from(
t in Transaction,
where: t.hash in ^ordered_transaction_hashes,
+ where: not is_nil(t.block_hash),
update: [
set: [
internal_transactions_indexed_at: ^timestamps.updated_at,
@@ -180,10 +183,8 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactions do
]
)
- transaction_count = Enum.count(ordered_transaction_hashes)
-
try do
- {^transaction_count, result} = repo.update_all(query, [], timeout: timeout)
+ {_transaction_count, result} = repo.update_all(query, [], timeout: timeout)
{:ok, result}
rescue
@@ -191,4 +192,23 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactions do
{:error, %{exception: postgrex_error, transaction_hashes: ordered_transaction_hashes}}
end
end
+
+ defp reject_pending_transactions(ordered_changes_list, repo) do
+ transaction_hashes =
+ ordered_changes_list
+ |> Enum.map(& &1.transaction_hash)
+ |> Enum.dedup()
+
+ query =
+ from(t in Transaction,
+ where: t.hash in ^transaction_hashes,
+ where: is_nil(t.block_hash),
+ select: t.hash
+ )
+
+ pending_transactions = repo.all(query)
+
+ ordered_changes_list
+ |> Enum.reject(fn %{transaction_hash: hash} -> Enum.member?(pending_transactions, hash) end)
+ end
end
diff --git a/apps/explorer/lib/explorer/chain/internal_transaction.ex b/apps/explorer/lib/explorer/chain/internal_transaction.ex
index 1231677a57..77f7d15da2 100644
--- a/apps/explorer/lib/explorer/chain/internal_transaction.ex
+++ b/apps/explorer/lib/explorer/chain/internal_transaction.ex
@@ -392,7 +392,7 @@ defmodule Explorer.Chain.InternalTransaction do
@create_required_fields ~w(from_address_hash gas index init trace_address transaction_hash value)a
@create_allowed_fields @create_optional_fields ++ @create_required_fields
- defp type_changeset(changeset, attrs, :create) do
+ defp type_changeset(changeset, attrs, type) when type in [:create, :create2] do
changeset
|> cast(attrs, @create_allowed_fields)
|> validate_required(@create_required_fields)
@@ -537,7 +537,7 @@ defmodule Explorer.Chain.InternalTransaction do
|> put_raw_call_error_or_result(transaction)
end
- defp internal_transaction_to_raw(%{type: :create} = transaction) do
+ defp internal_transaction_to_raw(%{type: type} = transaction) when type in [:create, :create2] do
%{
from_address_hash: from_address_hash,
gas: gas,
@@ -549,7 +549,7 @@ defmodule Explorer.Chain.InternalTransaction do
action = %{"from" => from_address_hash, "gas" => gas, "init" => init, "value" => value}
%{
- "type" => "create",
+ "type" => Atom.to_string(type),
"action" => Action.to_raw(action),
"traceAddress" => trace_address
}
diff --git a/apps/explorer/lib/explorer/chain/internal_transaction/type.ex b/apps/explorer/lib/explorer/chain/internal_transaction/type.ex
index 4133dcf45f..0a13587afe 100644
--- a/apps/explorer/lib/explorer/chain/internal_transaction/type.ex
+++ b/apps/explorer/lib/explorer/chain/internal_transaction/type.ex
@@ -11,7 +11,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
* `:reward`
* `:selfdestruct`
"""
- @type t :: :call | :create | :reward | :selfdestruct
+ @type t :: :call | :create | :create2 | :reward | :selfdestruct
@doc """
Casts `term` to `t:t/0`
@@ -22,6 +22,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast(:create)
{:ok, :create}
+ iex> Explorer.Chain.InternalTransaction.Type.cast(:create2)
+ {:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast(:reward)
{:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast(:selfdestruct)
@@ -33,6 +35,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast("create")
{:ok, :create}
+ iex> Explorer.Chain.InternalTransaction.Type.cast("create2")
+ {:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast("reward")
{:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast("selfdestruct")
@@ -53,9 +57,10 @@ defmodule Explorer.Chain.InternalTransaction.Type do
"""
@impl Ecto.Type
@spec cast(term()) :: {:ok, t()} | :error
- def cast(t) when t in ~w(call create selfdestruct reward)a, do: {:ok, t}
+ def cast(t) when t in ~w(call create create2 selfdestruct reward)a, do: {:ok, t}
def cast("call"), do: {:ok, :call}
def cast("create"), do: {:ok, :create}
+ def cast("create2"), do: {:ok, :create2}
def cast("reward"), do: {:ok, :reward}
def cast("selfdestruct"), do: {:ok, :selfdestruct}
def cast(_), do: :error
@@ -67,6 +72,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, "call"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:create)
{:ok, "create"}
+ iex> Explorer.Chain.InternalTransaction.Type.dump(:create2)
+ {:ok, "create2"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:reward)
{:ok, "reward"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:selfdestruct)
@@ -87,6 +94,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec dump(term()) :: {:ok, String.t()} | :error
def dump(:call), do: {:ok, "call"}
def dump(:create), do: {:ok, "create"}
+ def dump(:create2), do: {:ok, "create2"}
def dump(:reward), do: {:ok, "reward"}
def dump(:selfdestruct), do: {:ok, "selfdestruct"}
def dump(_), do: :error
@@ -98,6 +106,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.load("create")
{:ok, :create}
+ iex> Explorer.Chain.InternalTransaction.Type.load("create2")
+ {:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.load("reward")
{:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.load("selfdestruct")
@@ -118,6 +128,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec load(term()) :: {:ok, t()} | :error
def load("call"), do: {:ok, :call}
def load("create"), do: {:ok, :create}
+ def load("create2"), do: {:ok, :create2}
def load("reward"), do: {:ok, :reward}
def load("selfdestruct"), do: {:ok, :selfdestruct}
# deprecated
diff --git a/apps/explorer/lib/explorer/chain/transaction.ex b/apps/explorer/lib/explorer/chain/transaction.ex
index 3b109504eb..78d162fa4e 100644
--- a/apps/explorer/lib/explorer/chain/transaction.ex
+++ b/apps/explorer/lib/explorer/chain/transaction.ex
@@ -416,7 +416,8 @@ defmodule Explorer.Chain.Transaction do
candidates_query =
from(
contract_method in ContractMethod,
- where: contract_method.identifier == ^method_id
+ where: contract_method.identifier == ^method_id,
+ limit: 1
)
candidates =
diff --git a/apps/explorer/lib/explorer/chain/wei.ex b/apps/explorer/lib/explorer/chain/wei.ex
index c1c434aa44..78483632a7 100644
--- a/apps/explorer/lib/explorer/chain/wei.ex
+++ b/apps/explorer/lib/explorer/chain/wei.ex
@@ -31,21 +31,25 @@ defmodule Explorer.Chain.Wei do
@impl Ecto.Type
def cast("0x" <> hex_wei) do
- with {int_wei, ""} <- Integer.parse(hex_wei, 16) do
- decimal = Decimal.new(int_wei)
- {:ok, %__MODULE__{value: decimal}}
- else
- _ -> :error
+ case Integer.parse(hex_wei, 16) do
+ {int_wei, ""} ->
+ decimal = Decimal.new(int_wei)
+ {:ok, %__MODULE__{value: decimal}}
+
+ _ ->
+ :error
end
end
@impl Ecto.Type
def cast(string_wei) when is_binary(string_wei) do
- with {int_wei, ""} <- Integer.parse(string_wei) do
- decimal = Decimal.new(int_wei)
- {:ok, %__MODULE__{value: decimal}}
- else
- _ -> :error
+ case Integer.parse(string_wei) do
+ {int_wei, ""} ->
+ decimal = Decimal.new(int_wei)
+ {:ok, %__MODULE__{value: decimal}}
+
+ _ ->
+ :error
end
end
diff --git a/apps/explorer/lib/explorer/counters/average_block_time.ex b/apps/explorer/lib/explorer/counters/average_block_time.ex
index 233c15f8b3..1065ede2bd 100644
--- a/apps/explorer/lib/explorer/counters/average_block_time.ex
+++ b/apps/explorer/lib/explorer/counters/average_block_time.ex
@@ -11,7 +11,7 @@ defmodule Explorer.Counters.AverageBlockTime do
alias Explorer.Repo
alias Timex.Duration
- @refresh_period 30 * 60 * 1_000
+ @refresh_period Application.get_env(:explorer, __MODULE__)[:period]
@doc """
Starts a process to periodically update the counter of the token holders.
diff --git a/apps/explorer/lib/explorer/eth_rpc.ex b/apps/explorer/lib/explorer/eth_rpc.ex
new file mode 100644
index 0000000000..e0864ac279
--- /dev/null
+++ b/apps/explorer/lib/explorer/eth_rpc.ex
@@ -0,0 +1,371 @@
+defmodule Explorer.EthRPC do
+ @moduledoc """
+ Ethreum JSON RPC methods logic implementation.
+ """
+
+ alias Ecto.Type, as: EctoType
+ alias Explorer.{Chain, Repo}
+ alias Explorer.Chain.{Block, Data, Hash, Hash.Address, Wei}
+ alias Explorer.Etherscan.Logs
+
+ @methods %{
+ "eth_getBalance" => %{
+ action: :eth_get_balance,
+ notes: """
+ the `earliest` parameter will not work as expected currently, because genesis block balances
+ are not currently imported
+ """,
+ example: """
+ {"id": 0, "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["0x0000000000000000000000000000000000000007", "2"]}
+ """
+ },
+ "eth_getLogs" => %{
+ action: :eth_get_logs,
+ notes: """
+ Will never return more than 1000 log entries.\n
+ For this reason, you can use pagination options to request the next page. Pagination options params: {"logIndex": "3D", "blockNumber": "6423AC", "transactionIndex": 53} which include parameters from the last log received from the previous request. These three parameters are required for pagination.
+ """,
+ example: """
+ {"id": 0, "jsonrpc": "2.0", "method": "eth_getLogs",
+ "params": [
+ {"address": "0xc78Be425090Dbd437532594D12267C5934Cc6c6f",
+ "paging_options": {"logIndex": "3D", "blockNumber": "6423AC", "transactionIndex": 53},
+ "fromBlock": "earliest",
+ "toBlock": "latest",
+ "topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]}]}
+ """
+ }
+ }
+
+ @index_to_word %{
+ 0 => "first",
+ 1 => "second",
+ 2 => "third",
+ 3 => "fourth"
+ }
+
+ def responses(requests) do
+ Enum.map(requests, fn request ->
+ with {:id, {:ok, id}} <- {:id, Map.fetch(request, "id")},
+ {:request, {:ok, result}} <- {:request, do_eth_request(request)} do
+ format_success(result, id)
+ else
+ {:id, :error} -> format_error("id is a required field", 0)
+ {:request, {:error, message}} -> format_error(message, Map.get(request, "id"))
+ end
+ end)
+ end
+
+ def eth_get_balance(address_param, block_param \\ nil) do
+ with {:address, {:ok, address}} <- {:address, Chain.string_to_address_hash(address_param)},
+ {:block, {:ok, block}} <- {:block, block_param(block_param)},
+ {:balance, {:ok, balance}} <- {:balance, Chain.get_balance_as_of_block(address, block)} do
+ {:ok, Wei.hex_format(balance)}
+ else
+ {:address, :error} ->
+ {:error, "Query parameter 'address' is invalid"}
+
+ {:block, :error} ->
+ {:error, "Query parameter 'block' is invalid"}
+
+ {:balance, {:error, :not_found}} ->
+ {:error, "Balance not found"}
+ end
+ end
+
+ def eth_get_logs(filter_options) do
+ with {:ok, address_or_topic_params} <- address_or_topic_params(filter_options),
+ {:ok, from_block_param, to_block_param} <- logs_blocks_filter(filter_options),
+ {:ok, from_block} <- cast_block(from_block_param),
+ {:ok, to_block} <- cast_block(to_block_param),
+ {:ok, paging_options} <- paging_options(filter_options) do
+ filter =
+ address_or_topic_params
+ |> Map.put(:from_block, from_block)
+ |> Map.put(:to_block, to_block)
+ |> Map.put(:allow_non_consensus, true)
+
+ logs =
+ filter
+ |> Logs.list_logs(paging_options)
+ |> Enum.map(&render_log/1)
+
+ {:ok, logs}
+ else
+ {:error, message} when is_bitstring(message) ->
+ {:error, message}
+
+ {:error, :empty} ->
+ {:ok, []}
+
+ _ ->
+ {:error, "Something went wrong."}
+ end
+ end
+
+ defp render_log(log) do
+ topics =
+ Enum.reject(
+ [log.first_topic, log.second_topic, log.third_topic, log.fourth_topic],
+ &is_nil/1
+ )
+
+ %{
+ "address" => to_string(log.address_hash),
+ "blockHash" => to_string(log.block_hash),
+ "blockNumber" => Integer.to_string(log.block_number, 16),
+ "data" => to_string(log.data),
+ "logIndex" => Integer.to_string(log.index, 16),
+ "removed" => log.block_consensus == false,
+ "topics" => topics,
+ "transactionHash" => to_string(log.transaction_hash),
+ "transactionIndex" => log.transaction_index,
+ "transactionLogIndex" => log.index,
+ "type" => "mined"
+ }
+ end
+
+ defp cast_block("0x" <> hexadecimal_digits = input) do
+ case Integer.parse(hexadecimal_digits, 16) do
+ {integer, ""} -> {:ok, integer}
+ _ -> {:error, input <> " is not a valid block number"}
+ end
+ end
+
+ defp cast_block(integer) when is_integer(integer), do: {:ok, integer}
+ defp cast_block(_), do: {:error, "invalid block number"}
+
+ defp address_or_topic_params(filter_options) do
+ address_param = Map.get(filter_options, "address")
+ topics_param = Map.get(filter_options, "topics")
+
+ with {:ok, address} <- validate_address(address_param),
+ {:ok, topics} <- validate_topics(topics_param) do
+ address_and_topics(address, topics)
+ end
+ end
+
+ defp address_and_topics(nil, nil), do: {:error, "Must supply one of address and topics"}
+ defp address_and_topics(address, nil), do: {:ok, %{address_hash: address}}
+ defp address_and_topics(nil, topics), do: {:ok, topics}
+ defp address_and_topics(address, topics), do: {:ok, Map.put(topics, :address_hash, address)}
+
+ defp validate_address(nil), do: {:ok, nil}
+
+ defp validate_address(address) do
+ case Address.cast(address) do
+ {:ok, address} -> {:ok, address}
+ :error -> {:error, "invalid address"}
+ end
+ end
+
+ defp validate_topics(nil), do: {:ok, nil}
+ defp validate_topics([]), do: []
+
+ defp validate_topics(topics) when is_list(topics) do
+ topics
+ |> Stream.with_index()
+ |> Enum.reduce({:ok, %{}}, fn {topic, index}, {:ok, acc} ->
+ case cast_topics(topic) do
+ {:ok, data} ->
+ with_filter = Map.put(acc, String.to_existing_atom("#{@index_to_word[index]}_topic"), data)
+
+ {:ok, add_operator(with_filter, index)}
+
+ :error ->
+ {:error, "invalid topics"}
+ end
+ end)
+ end
+
+ defp add_operator(filters, 0), do: filters
+
+ defp add_operator(filters, index) do
+ Map.put(filters, String.to_existing_atom("topic#{index - 1}_#{index}_opr"), "and")
+ end
+
+ defp cast_topics(topics) when is_list(topics) do
+ case EctoType.cast({:array, Data}, topics) do
+ {:ok, data} -> {:ok, Enum.map(data, &to_string/1)}
+ :error -> :error
+ end
+ end
+
+ defp cast_topics(topic) do
+ case Data.cast(topic) do
+ {:ok, data} -> {:ok, to_string(data)}
+ :error -> :error
+ end
+ end
+
+ defp logs_blocks_filter(filter_options) do
+ with {:filter, %{"blockHash" => block_hash_param}} <- {:filter, filter_options},
+ {:block_hash, {:ok, block_hash}} <- {:block_hash, Hash.Full.cast(block_hash_param)},
+ {:block, %{number: number}} <- {:block, Repo.get(Block, block_hash)} do
+ {:ok, number, number}
+ else
+ {:filter, filters} ->
+ from_block = Map.get(filters, "fromBlock", "latest")
+ to_block = Map.get(filters, "toBlock", "latest")
+
+ max_block_number =
+ if from_block == "latest" || to_block == "latest" do
+ max_consensus_block_number()
+ end
+
+ pending_block_number =
+ if from_block == "pending" || to_block == "pending" do
+ max_non_consensus_block_number(max_block_number)
+ end
+
+ if is_nil(pending_block_number) && from_block == "pending" && to_block == "pending" do
+ {:error, :empty}
+ else
+ to_block_numbers(from_block, to_block, max_block_number, pending_block_number)
+ end
+
+ {:block, _} ->
+ {:error, "Invalid Block Hash"}
+
+ {:block_hash, _} ->
+ {:error, "Invalid Block Hash"}
+ end
+ end
+
+ defp paging_options(%{
+ "paging_options" => %{
+ "logIndex" => log_index,
+ "transactionIndex" => transaction_index,
+ "blockNumber" => block_number
+ }
+ })
+ when is_integer(transaction_index) do
+ with {:ok, parsed_block_number} <- to_number(block_number, "invalid block number"),
+ {:ok, parsed_log_index} <- to_number(log_index, "invalid log index") do
+ {:ok,
+ %{
+ log_index: parsed_log_index,
+ transaction_index: transaction_index,
+ block_number: parsed_block_number
+ }}
+ end
+ end
+
+ defp paging_options(_), do: {:ok, nil}
+
+ defp to_block_numbers(from_block, to_block, max_block_number, pending_block_number) do
+ actual_pending_block_number = pending_block_number || max_block_number
+
+ with {:ok, from} <-
+ to_block_number(from_block, max_block_number, actual_pending_block_number),
+ {:ok, to} <- to_block_number(to_block, max_block_number, actual_pending_block_number) do
+ {:ok, from, to}
+ end
+ end
+
+ defp to_block_number(integer, _, _) when is_integer(integer), do: {:ok, integer}
+ defp to_block_number("latest", max_block_number, _), do: {:ok, max_block_number || 0}
+ defp to_block_number("earliest", _, _), do: {:ok, 0}
+ defp to_block_number("pending", max_block_number, nil), do: {:ok, max_block_number || 0}
+ defp to_block_number("pending", _, pending), do: {:ok, pending}
+
+ defp to_block_number("0x" <> number, _, _) do
+ case Integer.parse(number, 16) do
+ {integer, ""} -> {:ok, integer}
+ _ -> {:error, "invalid block number"}
+ end
+ end
+
+ defp to_block_number(number, _, _) when is_bitstring(number) do
+ case Integer.parse(number, 16) do
+ {integer, ""} -> {:ok, integer}
+ _ -> {:error, "invalid block number"}
+ end
+ end
+
+ defp to_block_number(_, _, _), do: {:error, "invalid block number"}
+
+ defp to_number(number, error_message) when is_bitstring(number) do
+ case Integer.parse(number, 16) do
+ {integer, ""} -> {:ok, integer}
+ _ -> {:error, error_message}
+ end
+ end
+
+ defp to_number(_, error_message), do: {:error, error_message}
+
+ defp max_non_consensus_block_number(max) do
+ case Chain.max_non_consensus_block_number(max) do
+ {:ok, number} -> number
+ _ -> nil
+ end
+ end
+
+ defp max_consensus_block_number do
+ case Chain.max_consensus_block_number() do
+ {:ok, number} -> number
+ _ -> nil
+ end
+ end
+
+ defp format_success(result, id) do
+ %{result: result, id: id}
+ end
+
+ defp format_error(message, id) do
+ %{error: message, id: id}
+ end
+
+ defp do_eth_request(%{"jsonrpc" => rpc_version}) when rpc_version != "2.0" do
+ {:error, "invalid rpc version"}
+ end
+
+ defp do_eth_request(%{"jsonrpc" => "2.0", "method" => method, "params" => params})
+ when is_list(params) do
+ with {:ok, action} <- get_action(method),
+ {:correct_arity, true} <-
+ {:correct_arity, :erlang.function_exported(__MODULE__, action, Enum.count(params))} do
+ apply(__MODULE__, action, params)
+ else
+ {:correct_arity, _} ->
+ {:error, "Incorrect number of params."}
+
+ _ ->
+ {:error, "Action not found."}
+ end
+ end
+
+ defp do_eth_request(%{"params" => _params, "method" => _}) do
+ {:error, "Invalid params. Params must be a list."}
+ end
+
+ defp do_eth_request(_) do
+ {:error, "Method, params, and jsonrpc, are all required parameters."}
+ end
+
+ defp get_action(action) do
+ case Map.get(@methods, action) do
+ %{action: action} ->
+ {:ok, action}
+
+ _ ->
+ :error
+ end
+ end
+
+ defp block_param("latest"), do: {:ok, :latest}
+ defp block_param("earliest"), do: {:ok, :earliest}
+ defp block_param("pending"), do: {:ok, :pending}
+
+ defp block_param(string_integer) when is_bitstring(string_integer) do
+ case Integer.parse(string_integer) do
+ {integer, ""} -> {:ok, integer}
+ _ -> :error
+ end
+ end
+
+ defp block_param(nil), do: {:ok, :latest}
+ defp block_param(_), do: :error
+
+ def methods, do: @methods
+end
diff --git a/apps/explorer/lib/explorer/etherscan/logs.ex b/apps/explorer/lib/explorer/etherscan/logs.ex
index 9e9d70ae02..336eae106b 100644
--- a/apps/explorer/lib/explorer/etherscan/logs.ex
+++ b/apps/explorer/lib/explorer/etherscan/logs.ex
@@ -5,7 +5,7 @@ defmodule Explorer.Etherscan.Logs do
"""
- import Ecto.Query, only: [from: 2, where: 3, subquery: 1]
+ import Ecto.Query, only: [from: 2, where: 3, subquery: 1, order_by: 3]
alias Explorer.Chain.{Block, InternalTransaction, Log, Transaction}
alias Explorer.Repo
@@ -38,6 +38,8 @@ defmodule Explorer.Etherscan.Logs do
:type
]
+ @default_paging_options %{block_number: nil, transaction_index: nil, log_index: nil}
+
@doc """
Gets a list of logs that meet the criteria in a given filter map.
@@ -68,7 +70,10 @@ defmodule Explorer.Etherscan.Logs do
"""
@spec list_logs(map()) :: [map()]
- def list_logs(%{address_hash: address_hash} = filter) when not is_nil(address_hash) do
+ def list_logs(filter, paging_options \\ @default_paging_options)
+
+ def list_logs(%{address_hash: address_hash} = filter, paging_options) when not is_nil(address_hash) do
+ paging_options = if is_nil(paging_options), do: @default_paging_options, else: paging_options
prepared_filter = Map.merge(@base_filter, filter)
logs_query = where_topic_match(Log, prepared_filter)
@@ -134,14 +139,18 @@ defmodule Explorer.Etherscan.Logs do
)
end
- Repo.all(query_with_consensus)
+ query_with_consensus
+ |> order_by([log], asc: log.index)
+ |> page_logs(paging_options)
+ |> Repo.all()
end
# Since address_hash was not present, we know that a
# topic filter has been applied, so we use a different
# query that is optimized for a logs filter over an
# address_hash
- def list_logs(filter) do
+ def list_logs(filter, paging_options) do
+ paging_options = if is_nil(paging_options), do: @default_paging_options, else: paging_options
prepared_filter = Map.merge(@base_filter, filter)
logs_query = where_topic_match(Log, prepared_filter)
@@ -182,7 +191,10 @@ defmodule Explorer.Etherscan.Logs do
select_merge: map(log, ^@log_fields)
)
- Repo.all(query_with_block_transaction_data)
+ query_with_block_transaction_data
+ |> order_by([log], asc: log.index)
+ |> page_logs(paging_options)
+ |> Repo.all()
end
@topics [
@@ -231,4 +243,17 @@ defmodule Explorer.Etherscan.Logs do
end
defp where_multiple_topics_match(query, _, _, _), do: query
+
+ defp page_logs(query, %{block_number: nil, transaction_index: nil, log_index: nil}) do
+ query
+ end
+
+ defp page_logs(query, %{block_number: block_number, transaction_index: transaction_index, log_index: log_index}) do
+ from(
+ data in query,
+ where:
+ data.index > ^log_index and data.block_number >= ^block_number and
+ data.transaction_index >= ^transaction_index
+ )
+ end
end
diff --git a/apps/explorer/lib/explorer/market/market_history_cache.ex b/apps/explorer/lib/explorer/market/market_history_cache.ex
index 04b6193716..4ed3d9b7d2 100644
--- a/apps/explorer/lib/explorer/market/market_history_cache.ex
+++ b/apps/explorer/lib/explorer/market/market_history_cache.ex
@@ -12,7 +12,7 @@ defmodule Explorer.Market.MarketHistoryCache do
@last_update_key :last_update
@history_key :history
# 6 hours
- @cache_period 1_000 * 60 * 60 * 6
+ @cache_period Application.get_env(:explorer, __MODULE__)[:period]
@recent_days 30
def fetch do
diff --git a/apps/explorer/lib/explorer/smart_contract/reader.ex b/apps/explorer/lib/explorer/smart_contract/reader.ex
index 72b40f55a4..cc3aae5e83 100644
--- a/apps/explorer/lib/explorer/smart_contract/reader.ex
+++ b/apps/explorer/lib/explorer/smart_contract/reader.ex
@@ -8,7 +8,7 @@ defmodule Explorer.SmartContract.Reader do
alias EthereumJSONRPC.Contract
alias Explorer.Chain
- alias Explorer.Chain.Hash
+ alias Explorer.Chain.{Hash, SmartContract}
@typedoc """
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 """
Queries the contract functions on the blockchain and returns the call results.
+ Optionally accepts the abi if it has already been fetched.
+
## Examples
Note that for this example to work the database must be up to date with the
@@ -57,14 +59,20 @@ defmodule Explorer.SmartContract.Reader do
)
# => %{"sum" => {:error, "Data overflow encoding int, data `abc` cannot fit in 256 bits"}}
"""
- @spec query_verified_contract(Hash.Address.t(), functions()) :: functions_results()
- def query_verified_contract(address_hash, functions) do
+ @spec query_verified_contract(Hash.Address.t(), functions(), SmartContract.abi() | nil) :: functions_results()
+ def query_verified_contract(address_hash, functions, mabi \\ nil) do
contract_address = Hash.to_string(address_hash)
abi =
- address_hash
- |> Chain.address_hash_to_smart_contract()
- |> Map.get(:abi)
+ case mabi do
+ nil ->
+ address_hash
+ |> Chain.address_hash_to_smart_contract()
+ |> Map.get(:abi)
+
+ _ ->
+ mabi
+ end
query_contract(contract_address, abi, functions)
end
@@ -156,41 +164,41 @@ defmodule Explorer.SmartContract.Reader do
"""
@spec read_only_functions(Hash.t()) :: [%{}]
def read_only_functions(contract_address_hash) do
- contract_address_hash
- |> Chain.address_hash_to_smart_contract()
- |> Map.get(:abi, [])
- |> Enum.filter(& &1["constant"])
- |> fetch_current_value_from_blockchain(contract_address_hash, [])
- |> Enum.reverse()
- end
-
- def fetch_current_value_from_blockchain(
- [%{"inputs" => []} = function | tail],
- contract_address_hash,
- acc
- ) do
- values =
- fetch_from_blockchain(contract_address_hash, %{
- name: function["name"],
- args: function["inputs"],
- outputs: function["outputs"]
- })
+ abi =
+ contract_address_hash
+ |> Chain.address_hash_to_smart_contract()
+ |> Map.get(:abi)
- formatted = Map.replace!(function, "outputs", values)
+ case abi do
+ nil ->
+ []
- fetch_current_value_from_blockchain(tail, contract_address_hash, [formatted | acc])
+ _ ->
+ abi
+ |> Enum.filter(& &1["constant"])
+ |> Enum.map(&fetch_current_value_from_blockchain(&1, abi, contract_address_hash))
+ end
end
- def fetch_current_value_from_blockchain([function | tail], contract_address_hash, acc) do
- values = link_outputs_and_values(%{}, Map.get(function, "outputs", []), function["name"])
+ defp fetch_current_value_from_blockchain(function, abi, contract_address_hash) do
+ values =
+ case function do
+ %{"inputs" => []} ->
+ name = function["name"]
+ args = function["inputs"]
+ outputs = function["outputs"]
+
+ contract_address_hash
+ |> query_verified_contract(%{name => normalize_args(args)}, abi)
+ |> link_outputs_and_values(outputs, name)
- formatted = Map.replace!(function, "outputs", values)
+ _ ->
+ link_outputs_and_values(%{}, Map.get(function, "outputs", []), function["name"])
+ end
- fetch_current_value_from_blockchain(tail, contract_address_hash, [formatted | acc])
+ Map.replace!(function, "outputs", values)
end
- def fetch_current_value_from_blockchain([], _contract_address_hash, acc), do: acc
-
@doc """
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()]}) :: [%{}]
def query_function(contract_address_hash, %{name: name, args: args}) do
- function =
+ abi =
contract_address_hash
|> Chain.address_hash_to_smart_contract()
- |> Map.get(:abi, [])
- |> Enum.filter(fn function -> function["name"] == name end)
- |> List.first()
-
- fetch_from_blockchain(contract_address_hash, %{
- name: name,
- args: args,
- outputs: function["outputs"]
- })
- end
+ |> Map.get(:abi)
+
+ outputs =
+ case abi do
+ nil ->
+ nil
+
+ _ ->
+ function =
+ abi
+ |> Enum.filter(fn function -> function["name"] == name end)
+ |> List.first()
+
+ function["outputs"]
+ end
- defp fetch_from_blockchain(contract_address_hash, %{name: name, args: args, outputs: outputs}) do
contract_address_hash
- |> query_verified_contract(%{name => normalize_args(args)})
+ |> query_verified_contract(%{name => normalize_args(args)}, abi)
|> link_outputs_and_values(outputs, name)
end
diff --git a/apps/explorer/mix.exs b/apps/explorer/mix.exs
index 4956363cc4..4d73894d5e 100644
--- a/apps/explorer/mix.exs
+++ b/apps/explorer/mix.exs
@@ -68,19 +68,19 @@ defmodule Explorer.Mixfile do
{:bypass, "~> 1.0", only: :test},
{:briefly, "~> 0.4", github: "CargoSense/briefly"},
{:comeonin, "~> 4.0"},
- {:credo, "1.0.0", only: :test, runtime: false},
+ {:credo, "~> 1.1", only: :test, runtime: false},
# For Absinthe to load data in batches
{:dataloader, "~> 1.0.0"},
{:decimal, "~> 1.0"},
{:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false},
# `override: true` for `ex_machina` compatibility
- {:ecto, "~> 3.0", override: true},
+ {:ecto, "~> 3.1", override: true},
# Storing blockchain data and derived data in PostgreSQL.
- {:ecto_sql, "~> 3.0"},
+ {:ecto_sql, "~> 3.1"},
# JSONRPC access to query smart contracts
{:ethereum_jsonrpc, in_umbrella: true},
# Data factory for testing
- {:ex_machina, "~> 2.1", only: [:test]},
+ {:ex_machina, "~> 2.3", only: [:test]},
# Code coverage
{:excoveralls, "~> 0.10.0", only: [:test], github: "KronicDeth/excoveralls", branch: "circle-workflows"},
{:exvcr, "~> 0.10", only: :test},
@@ -98,12 +98,7 @@ defmodule Explorer.Mixfile do
# For compatibility with `prometheus_process_collector`, which hasn't been updated yet
{:prometheus, "~> 4.0", override: true},
# Prometheus metrics for query duration
- {
- :prometheus_ecto,
- "~> 1.3",
- # Ecto 3.0 compatibility
- github: "deadtrickster/prometheus-ecto", ref: "650a403183f6a2fb6b682d7fbcba8bf9d24fe1e4"
- },
+ {:prometheus_ecto, "~> 1.4.3"},
# bypass optional dependency
{:plug_cowboy, "~> 2.0", only: [:dev, :test]},
{:que, "~> 0.10.1"},
@@ -115,9 +110,9 @@ defmodule Explorer.Mixfile do
# `:spandex` tracing of `:ecto`
{:spandex_ecto, "~> 0.4.0"},
# Attach `:prometheus_ecto` to `:ecto`
- {:telemetry, "~> 0.3.0"},
+ {:telemetry, "~> 0.4.0"},
# `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0`
- {:timex, "~> 3.4"},
+ {:timex, "~> 3.6"},
{:con_cache, "~> 0.13"}
]
end
diff --git a/apps/explorer/priv/repo/migrations/20181108205650_additional_internal_transaction_constraints.exs b/apps/explorer/priv/repo/migrations/20181108205650_additional_internal_transaction_constraints.exs
index de554e5acf..5caa150eaa 100644
--- a/apps/explorer/priv/repo/migrations/20181108205650_additional_internal_transaction_constraints.exs
+++ b/apps/explorer/priv/repo/migrations/20181108205650_additional_internal_transaction_constraints.exs
@@ -7,6 +7,9 @@ defmodule Explorer.Repo.Migrations.AdditionalInternalTransactionConstraints do
mix ecto.migrate
psql -d $DATABASE -a -f priv/repo/migrations/scripts/20181108205650_additional_internal_transaction_constraints.sql
```
+
+ NOTE: you may want to consider using `apps/explorer/priv/repo/migrations/scripts/20181108205650_large_additional_internal_transaction_constraints.sql`
+ instead if you are dealing with a very large number of transactions/internal_transactions.
"""
use Ecto.Migration
diff --git a/apps/explorer/priv/repo/migrations/scripts/20181108205650_large_additional_internal_transaction_constraints.sql b/apps/explorer/priv/repo/migrations/scripts/20181108205650_large_additional_internal_transaction_constraints.sql
new file mode 100644
index 0000000000..cb82ce8847
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/scripts/20181108205650_large_additional_internal_transaction_constraints.sql
@@ -0,0 +1,75 @@
+-- This script is a reimplementation of `20181108205650_additional_internal_transaction_constraints.sql`
+-- that is meant to be executed on DBs where the number of transactions and/or
+-- internal_transactions is very large.
+-- To check the progress it is advised to run this in a `tmux` session or save
+-- the output to a file.
+-- IMPORTANT NOTE: after making all the corrections needed the script will NOT
+-- run the constraint validations because this may be a very long and taxing
+-- operation. To validate the constraint one can run, after the script fininshed:
+
+-- ALTER TABLE internal_transactions VALIDATE CONSTRAINT call_has_call_type;
+-- ALTER TABLE internal_transactions VALIDATE CONSTRAINT call_has_input;
+-- ALTER TABLE internal_transactions VALIDATE CONSTRAINT create_has_init;
+
+DO $$
+DECLARE
+ batch_size integer := 10000; -- HOW MANY ITEMS WILL BE UPDATED AT A TIME
+ last_transaction_hash bytea; -- WILL CHECK ONLY TRANSACTIONS FOLLOWING THIS HASH (DESC)
+ last_fetched_batch_size integer;
+BEGIN
+ RAISE NOTICE 'STARTING SCRIPT';
+ CREATE TEMP TABLE transactions_with_deprecated_internal_transactions(hash bytea NOT NULL);
+
+ LOOP
+ RAISE NOTICE 'Fetching new batch of % transactions to correct', batch_size;
+
+ INSERT INTO transactions_with_deprecated_internal_transactions
+ SELECT DISTINCT transaction_hash
+ FROM internal_transactions
+ WHERE
+ (last_transaction_hash IS NULL OR transaction_hash < last_transaction_hash) AND
+ -- call_has_call_type CONSTRAINT
+ ((type = 'call' AND call_type IS NULL) OR
+ -- call_has_input CONSTRAINT
+ (type = 'call' AND input IS NULL) OR
+ -- create_has_init CONSTRAINT
+ (type = 'create' AND init is NULL))
+ ORDER BY transaction_hash DESC LIMIT batch_size;
+
+ SELECT INTO last_fetched_batch_size count(*) FROM transactions_with_deprecated_internal_transactions;
+
+ RAISE NOTICE 'Batch of % transactions was fetched, starting their deprecation', last_fetched_batch_size;
+
+ -- UPDATE TRANSACTIONS
+ UPDATE transactions
+ SET internal_transactions_indexed_at = NULL,
+ error = NULL
+ FROM transactions_with_deprecated_internal_transactions
+ WHERE transactions.hash = transactions_with_deprecated_internal_transactions.hash;
+
+ -- REMOVE THE DEPRECATED internal_transactions
+ DELETE FROM internal_transactions
+ USING transactions_with_deprecated_internal_transactions
+ WHERE internal_transactions.transaction_hash = transactions_with_deprecated_internal_transactions.hash;
+
+ -- COMMIT THE BATCH UPDATES
+ CHECKPOINT;
+
+ -- UPDATE last_transaction_hash TO KEEP TRACK OF ROWS ALREADY CHECKED
+ SELECT INTO last_transaction_hash hash
+ FROM transactions_with_deprecated_internal_transactions
+ ORDER BY hash ASC LIMIT 1;
+
+ RAISE NOTICE 'Last batch completed, last transaction hash: %', last_transaction_hash;
+
+ -- CLEAR THE TEMP TABLE
+ DELETE FROM transactions_with_deprecated_internal_transactions;
+
+ -- EXIT IF ALL internal_transactions HAVE BEEN CHECKED ALREADY
+ EXIT WHEN last_fetched_batch_size != batch_size;
+ END LOOP;
+
+ RAISE NOTICE 'SCRIPT FINISHED, all affected transactions have been deprecated';
+
+ DROP TABLE transactions_with_deprecated_internal_transactions;
+END $$;
diff --git a/apps/explorer/test/explorer/chain/import/runner/internal_transactions_test.exs b/apps/explorer/test/explorer/chain/import/runner/internal_transactions_test.exs
index f5c080991e..66d62ae940 100644
--- a/apps/explorer/test/explorer/chain/import/runner/internal_transactions_test.exs
+++ b/apps/explorer/test/explorer/chain/import/runner/internal_transactions_test.exs
@@ -2,7 +2,7 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do
use Explorer.DataCase
alias Ecto.Multi
- alias Explorer.Chain.{Data, Wei, Transaction}
+ alias Explorer.Chain.{Data, Wei, Transaction, InternalTransaction}
alias Explorer.Chain.Import.Runner.InternalTransactions
describe "run/1" do
@@ -20,6 +20,28 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do
assert :error == Repo.get(Transaction, transaction.hash).status
end
+
+ test "pending transactions don't get updated not its internal_transactions inserted" do
+ transaction = insert(:transaction) |> with_block(status: :ok)
+ pending = insert(:transaction)
+
+ assert :ok == transaction.status
+ assert is_nil(pending.block_hash)
+
+ index = 0
+
+ transaction_changes = make_internal_transaction_changes(transaction.hash, index, nil)
+ pending_changes = make_internal_transaction_changes(pending.hash, index, nil)
+
+ assert {:ok, _} = run_internal_transactions([transaction_changes, pending_changes])
+
+ assert %InternalTransaction{} =
+ Repo.one(from(i in InternalTransaction, where: i.transaction_hash == ^transaction.hash))
+
+ assert from(i in InternalTransaction, where: i.transaction_hash == ^pending.hash) |> Repo.one() |> is_nil()
+
+ assert is_nil(Repo.get(Transaction, pending.hash).block_hash)
+ end
end
defp run_internal_transactions(changes_list) when is_list(changes_list) do
diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs
index 38e61dee7d..234252dbe4 100644
--- a/apps/explorer/test/explorer/chain_test.exs
+++ b/apps/explorer/test/explorer/chain_test.exs
@@ -50,21 +50,35 @@ defmodule Explorer.ChainTest do
end
end
- describe "last_block_status/0" do
+ describe "last_db_block_status/0" do
test "return no_blocks errors if db is empty" do
- assert {:error, :no_blocks} = Chain.last_block_status()
+ assert {:error, :no_blocks} = Chain.last_db_block_status()
end
test "returns {:ok, last_block_period} if block is in healthy period" do
insert(:block, consensus: true)
- assert {:ok, _, _} = Chain.last_block_status()
+ assert {:ok, _, _} = Chain.last_db_block_status()
end
test "return {:ok, last_block_period} if block is not in healthy period" do
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
- assert {:error, _, _} = Chain.last_block_status()
+ assert {:error, _, _} = Chain.last_db_block_status()
+ end
+ end
+
+ describe "last_cache_block_status/0" do
+ test "returns success if cache is not stale" do
+ insert(:block, consensus: true)
+
+ assert {:ok, _, _} = Chain.last_cache_block_status()
+ end
+
+ test "return error if cache is stale" do
+ insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
+
+ assert {:error, _, _} = Chain.last_cache_block_status()
end
end
@@ -630,7 +644,7 @@ defmodule Explorer.ChainTest do
assert Repo.aggregate(Transaction, :count, :hash) == 0
- assert [] = Chain.block_to_transactions(block)
+ assert [] = Chain.block_to_transactions(block.hash)
end
test "with transactions" do
@@ -639,7 +653,7 @@ defmodule Explorer.ChainTest do
|> insert()
|> with_block()
- assert [%Transaction{hash: ^transaction_hash}] = Chain.block_to_transactions(block)
+ assert [%Transaction{hash: ^transaction_hash}] = Chain.block_to_transactions(block.hash)
end
test "with transactions can be paginated by {index}" do
@@ -657,7 +671,7 @@ defmodule Explorer.ChainTest do
|> with_block(block)
assert second_page_hashes ==
- block
+ block.hash
|> Chain.block_to_transactions(paging_options: %PagingOptions{key: {index}, page_size: 50})
|> Enum.map(& &1.hash)
|> Enum.reverse()
@@ -683,7 +697,7 @@ defmodule Explorer.ChainTest do
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 length(fetched_transaction.token_transfers) == 2
end
@@ -693,7 +707,7 @@ defmodule Explorer.ChainTest do
test "without transactions" do
block = insert(:block)
- assert Chain.block_to_transaction_count(block) == 0
+ assert Chain.block_to_transaction_count(block.hash) == 0
end
test "with transactions" do
@@ -702,7 +716,7 @@ defmodule Explorer.ChainTest do
|> insert()
|> with_block()
- assert Chain.block_to_transaction_count(block) == 1
+ assert Chain.block_to_transaction_count(block.hash) == 1
end
end
@@ -2090,7 +2104,7 @@ defmodule Explorer.ChainTest do
test "with transaction without internal transactions" do
transaction = insert(:transaction)
- assert [] = Chain.transaction_to_internal_transactions(transaction)
+ assert [] = Chain.transaction_to_internal_transactions(transaction.hash)
end
test "with transaction with internal transactions returns all internal transactions for a given transaction hash" do
@@ -2117,7 +2131,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index
)
- results = [internal_transaction | _] = Chain.transaction_to_internal_transactions(transaction)
+ results = [internal_transaction | _] = Chain.transaction_to_internal_transactions(transaction.hash)
assert 2 == length(results)
@@ -2151,7 +2165,7 @@ defmodule Explorer.ChainTest do
to_address: %Ecto.Association.NotLoaded{},
transaction: %Transaction{block: %Ecto.Association.NotLoaded{}}
}
- ] = Chain.transaction_to_internal_transactions(transaction)
+ ] = Chain.transaction_to_internal_transactions(transaction.hash)
assert [
%InternalTransaction{
@@ -2161,7 +2175,7 @@ defmodule Explorer.ChainTest do
}
] =
Chain.transaction_to_internal_transactions(
- transaction,
+ transaction.hash,
necessity_by_association: %{
:from_address => :optional,
:to_address => :optional,
@@ -2183,7 +2197,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index
)
- result = Chain.transaction_to_internal_transactions(transaction)
+ result = Chain.transaction_to_internal_transactions(transaction.hash)
assert Enum.empty?(result)
end
@@ -2202,7 +2216,7 @@ defmodule Explorer.ChainTest do
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}
end
@@ -2222,7 +2236,7 @@ defmodule Explorer.ChainTest do
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}
end
@@ -2243,7 +2257,7 @@ defmodule Explorer.ChainTest do
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}
end
@@ -2271,7 +2285,7 @@ defmodule Explorer.ChainTest do
)
result =
- transaction
+ transaction.hash
|> Chain.transaction_to_internal_transactions()
|> Enum.map(&{&1.transaction_hash, &1.index})
@@ -2301,17 +2315,17 @@ defmodule Explorer.ChainTest do
)
assert [{first_transaction_hash, first_index}, {second_transaction_hash, second_index}] ==
- transaction
+ transaction.hash
|> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {-1}, page_size: 2})
|> Enum.map(&{&1.transaction_hash, &1.index})
assert [{first_transaction_hash, first_index}] ==
- transaction
+ transaction.hash
|> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {-1}, page_size: 1})
|> Enum.map(&{&1.transaction_hash, &1.index})
assert [{second_transaction_hash, second_index}] ==
- transaction
+ transaction.hash
|> Chain.transaction_to_internal_transactions(paging_options: %PagingOptions{key: {0}, page_size: 2})
|> Enum.map(&{&1.transaction_hash, &1.index})
end
@@ -2321,7 +2335,7 @@ defmodule Explorer.ChainTest do
test "without logs" do
transaction = insert(:transaction)
- assert [] = Chain.transaction_to_logs(transaction)
+ assert [] = Chain.transaction_to_logs(transaction.hash)
end
test "with logs" do
@@ -2332,7 +2346,7 @@ defmodule Explorer.ChainTest do
%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
test "with logs can be paginated" do
@@ -2349,7 +2363,7 @@ defmodule Explorer.ChainTest do
|> Enum.map(& &1.index)
assert second_page_indexes ==
- transaction
+ transaction.hash
|> Chain.transaction_to_logs(paging_options: %PagingOptions{key: {log.index}, page_size: 50})
|> Enum.map(& &1.index)
end
@@ -2364,7 +2378,7 @@ defmodule Explorer.ChainTest do
assert [%Log{address: %Address{}, transaction: %Transaction{}}] =
Chain.transaction_to_logs(
- transaction,
+ transaction.hash,
necessity_by_association: %{
address: :optional,
transaction: :optional
@@ -2376,7 +2390,7 @@ defmodule Explorer.ChainTest do
address: %Ecto.Association.NotLoaded{},
transaction: %Ecto.Association.NotLoaded{}
}
- ] = Chain.transaction_to_logs(transaction)
+ ] = Chain.transaction_to_logs(transaction.hash)
end
end
@@ -2384,7 +2398,7 @@ defmodule Explorer.ChainTest do
test "without token transfers" do
transaction = insert(:transaction)
- assert [] = Chain.transaction_to_token_transfers(transaction)
+ assert [] = Chain.transaction_to_token_transfers(transaction.hash)
end
test "with token transfers" do
@@ -2397,7 +2411,7 @@ defmodule Explorer.ChainTest do
insert(:token_transfer, transaction: transaction)
assert [%TokenTransfer{transaction_hash: ^transaction_hash, log_index: ^log_index}] =
- Chain.transaction_to_token_transfers(transaction)
+ Chain.transaction_to_token_transfers(transaction.hash)
end
test "token transfers necessity_by_association loads associations" do
@@ -2410,7 +2424,7 @@ defmodule Explorer.ChainTest do
assert [%TokenTransfer{token: %Token{}, transaction: %Transaction{}}] =
Chain.transaction_to_token_transfers(
- transaction,
+ transaction.hash,
necessity_by_association: %{
token: :optional,
transaction: :optional
@@ -2422,7 +2436,7 @@ defmodule Explorer.ChainTest do
token: %Ecto.Association.NotLoaded{},
transaction: %Ecto.Association.NotLoaded{}
}
- ] = Chain.transaction_to_token_transfers(transaction)
+ ] = Chain.transaction_to_token_transfers(transaction.hash)
end
end
@@ -2480,7 +2494,17 @@ defmodule Explorer.ChainTest do
insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil, names: [])
|> 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}
end
@@ -2523,11 +2547,11 @@ defmodule Explorer.ChainTest do
|> Decimal.add(Decimal.new(3))
|> Wei.from(:wei)
- assert expected == Chain.block_reward(block)
+ assert expected == Chain.block_reward(block.number)
end
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
diff --git a/apps/explorer/test/explorer/etherscan/logs_test.exs b/apps/explorer/test/explorer/etherscan/logs_test.exs
index 00050db6f4..490dce199d 100644
--- a/apps/explorer/test/explorer/etherscan/logs_test.exs
+++ b/apps/explorer/test/explorer/etherscan/logs_test.exs
@@ -158,6 +158,46 @@ defmodule Explorer.Etherscan.LogsTest do
assert found_log.transaction_hash == transaction_block1.hash
end
+ test "paginates logs" do
+ contract_address = insert(:contract_address)
+
+ transaction =
+ %Transaction{block: block} =
+ :transaction
+ |> insert(to_address: contract_address)
+ |> with_block()
+
+ inserted_records = insert_list(2000, :log, address: contract_address, transaction: transaction)
+
+ filter = %{
+ from_block: block.number,
+ to_block: block.number,
+ address_hash: contract_address.hash
+ }
+
+ first_found_logs = Logs.list_logs(filter)
+
+ assert Enum.count(first_found_logs) == 1_000
+
+ last_record = List.last(first_found_logs)
+
+ next_page_params = %{
+ log_index: last_record.index,
+ transaction_index: last_record.transaction_index,
+ block_number: transaction.block_number
+ }
+
+ second_found_logs = Logs.list_logs(filter, next_page_params)
+
+ assert Enum.count(second_found_logs) == 1_000
+
+ all_found_logs = first_found_logs ++ second_found_logs
+
+ assert Enum.all?(inserted_records, fn record ->
+ Enum.any?(all_found_logs, fn found_log -> found_log.index == record.index end)
+ end)
+ end
+
test "with a valid topic{x}" do
contract_address = insert(:contract_address)
diff --git a/apps/explorer/test/explorer/smart_contract/reader_test.exs b/apps/explorer/test/explorer/smart_contract/reader_test.exs
index ab63b74d1e..82f0a54385 100644
--- a/apps/explorer/test/explorer/smart_contract/reader_test.exs
+++ b/apps/explorer/test/explorer/smart_contract/reader_test.exs
@@ -102,7 +102,7 @@ defmodule Explorer.SmartContract.ReaderTest do
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
hash =
:smart_contract
diff --git a/apps/indexer/config/config.exs b/apps/indexer/config/config.exs
index 4e84e9bcfe..9ab951d668 100644
--- a/apps/indexer/config/config.exs
+++ b/apps/indexer/config/config.exs
@@ -35,7 +35,8 @@ config :indexer,
String.to_integer(System.get_env("TOKEN_METADATA_UPDATE_INTERVAL") || "#{2 * 24 * 60 * 60}"),
# bytes
memory_limit: 1 <<< 30,
- first_block: System.get_env("FIRST_BLOCK") || "0"
+ first_block: System.get_env("FIRST_BLOCK") || "0",
+ last_block: System.get_env("LAST_BLOCK") || ""
# config :indexer, Indexer.Fetcher.ReplacedTransaction.Supervisor, disabled?: true
# config :indexer, Indexer.Fetcher.BlockReward.Supervisor, disabled?: true
diff --git a/apps/indexer/lib/indexer/block/catchup/bound_interval_supervisor.ex b/apps/indexer/lib/indexer/block/catchup/bound_interval_supervisor.ex
index f1b216aa2b..b128ad4ca0 100644
--- a/apps/indexer/lib/indexer/block/catchup/bound_interval_supervisor.ex
+++ b/apps/indexer/lib/indexer/block/catchup/bound_interval_supervisor.ex
@@ -185,7 +185,12 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisor do
def handle_info(
{ref,
- %{first_block_number: first_block_number, missing_block_count: missing_block_count, shrunk: false = shrunk}},
+ %{
+ first_block_number: first_block_number,
+ last_block_number: last_block_number,
+ missing_block_count: missing_block_count,
+ shrunk: false = shrunk
+ }},
%__MODULE__{
bound_interval: bound_interval,
task: %Task{ref: ref}
@@ -197,7 +202,7 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisor do
0 ->
Logger.info("Index already caught up.",
first_block_number: first_block_number,
- last_block_number: 0,
+ last_block_number: last_block_number,
missing_block_count: 0,
shrunk: shrunk
)
diff --git a/apps/indexer/lib/indexer/block/catchup/fetcher.ex b/apps/indexer/lib/indexer/block/catchup/fetcher.ex
index bb15ebcd2d..f228551a37 100644
--- a/apps/indexer/lib/indexer/block/catchup/fetcher.ex
+++ b/apps/indexer/lib/indexer/block/catchup/fetcher.ex
@@ -72,7 +72,14 @@ defmodule Indexer.Block.Catchup.Fetcher do
) do
Logger.metadata(fetcher: :block_catchup)
- {:ok, latest_block_number} = EthereumJSONRPC.fetch_block_number_by_tag("latest", json_rpc_named_arguments)
+ {:ok, latest_block_number} =
+ case latest_block() do
+ nil ->
+ EthereumJSONRPC.fetch_block_number_by_tag("latest", json_rpc_named_arguments)
+
+ number ->
+ {:ok, number}
+ end
case latest_block_number do
# let realtime indexer get the genesis block
@@ -116,7 +123,7 @@ defmodule Indexer.Block.Catchup.Fetcher do
Shrinkable.shrunk?(sequence)
end
- %{first_block_number: first, missing_block_count: missing_block_count, shrunk: shrunk}
+ %{first_block_number: first, last_block_number: last, missing_block_count: missing_block_count, shrunk: shrunk}
end
end
@@ -337,4 +344,13 @@ defmodule Indexer.Block.Catchup.Fetcher do
_ -> 0
end
end
+
+ defp latest_block do
+ string_value = Application.get_env(:indexer, :last_block)
+
+ case Integer.parse(string_value) do
+ {integer, ""} -> integer
+ _ -> nil
+ end
+ end
end
diff --git a/apps/indexer/lib/indexer/fetcher/internal_transaction.ex b/apps/indexer/lib/indexer/fetcher/internal_transaction.ex
index 3b9746b838..7d93bbf64f 100644
--- a/apps/indexer/lib/indexer/fetcher/internal_transaction.ex
+++ b/apps/indexer/lib/indexer/fetcher/internal_transaction.ex
@@ -152,12 +152,6 @@ defmodule Indexer.Fetcher.InternalTransaction do
unique_entries = unique_entries(entries, variant)
- internal_transactions_indexed_at_blocks =
- case variant do
- EthereumJSONRPC.Parity -> Enum.map(unique_entries, &block_params/1)
- _ -> []
- end
-
unique_entries_count = Enum.count(unique_entries)
Logger.metadata(count: unique_entries_count)
@@ -176,47 +170,7 @@ defmodule Indexer.Fetcher.InternalTransaction do
end
|> case do
{:ok, internal_transactions_params} ->
- internal_transactions_params_without_failed_creations = remove_failed_creations(internal_transactions_params)
-
- addresses_params =
- Addresses.extract_addresses(%{
- internal_transactions: internal_transactions_params_without_failed_creations
- })
-
- address_hash_to_block_number =
- Enum.into(addresses_params, %{}, fn %{fetched_coin_balance_block_number: block_number, hash: hash} ->
- {hash, block_number}
- end)
-
- with {:ok, imported} <-
- Chain.import(%{
- addresses: %{params: addresses_params},
- internal_transactions: %{params: internal_transactions_params_without_failed_creations},
- internal_transactions_indexed_at_blocks: %{
- params: internal_transactions_indexed_at_blocks,
- with: :number_only_changeset
- },
- timeout: :infinity
- }) do
- async_import_coin_balances(imported, %{
- address_hash_to_fetched_balance_block_number: address_hash_to_block_number
- })
- else
- {:error, step, reason, _changes_so_far} ->
- Logger.error(
- fn ->
- [
- "failed to import internal transactions for transactions: ",
- inspect(reason)
- ]
- end,
- step: step,
- error_count: unique_entries_count
- )
-
- # re-queue the de-duped entries
- {:retry, unique_entries}
- end
+ import_internal_transaction(internal_transactions_params, json_rpc_named_arguments, unique_entries)
{:error, reason} ->
Logger.error(fn -> ["failed to fetch internal transactions for transactions: ", inspect(reason)] end,
@@ -231,6 +185,60 @@ defmodule Indexer.Fetcher.InternalTransaction do
end
end
+ defp import_internal_transaction(internal_transactions_params, json_rpc_named_arguments, unique_entries) do
+ internal_transactions_indexed_at_blocks =
+ case Keyword.fetch!(json_rpc_named_arguments, :variant) do
+ EthereumJSONRPC.Parity -> Enum.map(unique_entries, &block_params/1)
+ _ -> []
+ end
+
+ unique_entries_count = Enum.count(unique_entries)
+ internal_transactions_params_without_failed_creations = remove_failed_creations(internal_transactions_params)
+
+ addresses_params =
+ Addresses.extract_addresses(%{
+ internal_transactions: internal_transactions_params_without_failed_creations
+ })
+
+ address_hash_to_block_number =
+ Enum.into(addresses_params, %{}, fn %{fetched_coin_balance_block_number: block_number, hash: hash} ->
+ {hash, block_number}
+ end)
+
+ imports =
+ Chain.import(%{
+ addresses: %{params: addresses_params},
+ internal_transactions: %{params: internal_transactions_params_without_failed_creations},
+ internal_transactions_indexed_at_blocks: %{
+ params: internal_transactions_indexed_at_blocks,
+ with: :number_only_changeset
+ },
+ timeout: :infinity
+ })
+
+ case imports do
+ {:ok, imported} ->
+ async_import_coin_balances(imported, %{
+ address_hash_to_fetched_balance_block_number: address_hash_to_block_number
+ })
+
+ {:error, step, reason, _changes_so_far} ->
+ Logger.error(
+ fn ->
+ [
+ "failed to import internal transactions for transactions: ",
+ inspect(reason)
+ ]
+ end,
+ step: step,
+ error_count: unique_entries_count
+ )
+
+ # re-queue the de-duped entries
+ {:retry, unique_entries}
+ end
+ end
+
defp unique_entries(entries, EthereumJSONRPC.Parity), do: Enum.uniq(entries)
# Protection and improved reporting for https://github.com/poanetwork/blockscout/issues/289
diff --git a/docs/env-variables.md b/docs/env-variables.md
index d6dd56d7af..edb437ce2f 100644
--- a/docs/env-variables.md
+++ b/docs/env-variables.md
@@ -48,6 +48,7 @@ $ export NETWORK=POA
| `BLOCK_TRANSFORMER` | | Transformer for blocks: base or clique. | base | v1.3.4+ |
| `GRAPHIQL _TRANSACTION` | | Default transaction in query to GraphiQL. | (empty) | v1.3.4+ |
| `FIRST_BLOCK` | | The block number, where indexing begins from. | 0 | v1.3.8+ |
+| `LAST_BLOCK` | | The block number, where indexing stops. | (empty) | master |
| `TXS_COUNT_CACHE_PERIOD` | | Interval in seconds to restart the task, which calculates the total txs count. | 60 * 60 * 2 | v1.3.9+ |
| `ADDRESS_WITH_BALANCES` `_UPDATE_INTERVAL`| | Interval in seconds to restart the task, which calculates addresses with balances. | 30 * 60 | v1.3.9+ |
| `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ |
diff --git a/mix.lock b/mix.lock
index 5ff4c0f8d0..92fd054cb6 100644
--- a/mix.lock
+++ b/mix.lock
@@ -2,8 +2,8 @@
"abi": {:hex, :abi, "0.1.12", "87ae04cb09e2308db7b3c350584dc3934de0e308f6a056ba82be5756b081a1ca", [:mix], [{:exth_crypto, "~> 0.1.4", [hex: :exth_crypto, repo: "hexpm", optional: false]}], "hexpm"},
"abnf2": {:hex, :abnf2, "0.1.2", "6f8792b8ac3288dba5fc889c2bceae9fe78f74e1a7b36bea9726ffaa9d7bef95", [:mix], []},
"absinthe": {:hex, :absinthe, "1.4.14", "fef224a6aac63d6eaafbc0cb96040a8abcd572275b9b4db69d46329acdcae7c7", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
- "absinthe_phoenix": {:git, "https://github.com/ayrat555/absinthe_phoenix.git", "4104c7213c328c3698b52710d49cd6d85449305c", [branch: "master"]},
- "absinthe_plug": {:git, "https://github.com/ayrat555/absinthe_plug.git", "e74da0a6e004fe4126885b5f5f60a3e72abd70bb", [branch: "ab-allow-to-set-default-query"]},
+ "absinthe_phoenix": {:git, "https://github.com/ayrat555/absinthe_phoenix.git", "0f5127844a9e4e1c5fecb1fcee225894a2af6336", [branch: "master"]},
+ "absinthe_plug": {:git, "https://github.com/ayrat555/absinthe_plug.git", "cbe1c170e11e60b3b0146b925a1ce6ec562840ce", [branch: "ab-enable-default-query"]},
"absinthe_relay": {:hex, :absinthe_relay, "1.4.6", "ec0e2288994b388556247cf9601245abec785cdf206d6e844f2992d29de21624", [:mix], [{:absinthe, "~> 1.4.0", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
"accept": {:hex, :accept, "0.3.3", "548ebb6fb2e8b0d170e75bb6123aea6ceecb0189bb1231eeadf52eac08384a97", [:rebar3], [], "hexpm"},
"artificery": {:hex, :artificery, "0.2.6", "f602909757263f7897130cbd006b0e40514a541b148d366ad65b89236b93497a", [:mix], [], "hexpm"},
@@ -14,7 +14,8 @@
"briefly": {:git, "https://github.com/CargoSense/briefly.git", "2526e9674a4e6996137e066a1295ea60962712b8", []},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []},
"bypass": {:hex, :bypass, "1.0.0", "b78b3dcb832a71aca5259c1a704b2e14b55fd4e1327ff942598b4e7d1a7ad83d", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}], "hexpm"},
- "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
+ "certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
+ "cldr_utils": {:hex, :cldr_utils, "2.3.0", "e7e8b5ad7494a929c1b620cc489c3aa3f6e7e5299584c1a934bbdb56d1a53c70", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], []},
"comeonin": {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"},
"con_cache": {:hex, :con_cache, "0.13.1", "047e097ab2a8c6876e12d0c29e29a86d487b592df97b98e3e2abedad574e215d", [:mix], [], "hexpm"},
@@ -22,25 +23,27 @@
"cors_plug": {:hex, :cors_plug, "2.0.0", "238ddb479f92b38f6dc1ae44b8d81f0387f9519101a6da442d543ab70ee0e482", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"cowboy": {:hex, :cowboy, "2.6.1", "f2e06f757c337b3b311f9437e6e072b678fcd71545a7b2865bdaa154d078593f", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "2.7.0", "3ef16e77562f9855a2605900cedb15c1462d76fb1be6a32fc3ae91973ee543d2", [:rebar3], [], "hexpm"},
- "credo": {:hex, :credo, "1.0.0", "aaa40fdd0543a0cf8080e8c5949d8c25f0a24e4fc8c1d83d06c388f5e5e0ea42", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
+ "credo": {:hex, :credo, "1.1.2", "02b6422f3e659eb74b05aca3c20c1d8da0119a05ee82577a82e6c2938bf29f81", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
"csv": {:hex, :csv, "2.1.1", "a4c1a7c30d2151b6e4976cb2f52c0a1d49ec965afb737ed84a684bc4284d1627", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, optional: false]}]},
"dataloader": {:hex, :dataloader, "1.0.6", "fb724d6d3fb6acb87d27e3b32dea3a307936ad2d245faf9cf5221d1323d6a4ba", [:mix], [{:ecto, ">= 0.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
- "db_connection": {:hex, :db_connection, "2.0.3", "b4e8aa43c100e16f122ccd6798cd51c48c79fd391c39d411f42b3cd765daccb0", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
- "decimal": {:hex, :decimal, "1.6.0", "bfd84d90ff966e1f5d4370bdd3943432d8f65f07d3bab48001aebd7030590dcc", [:mix], [], "hexpm"},
+ "db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
+ "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
"decorator": {:hex, :decorator, "1.3.0", "6203dbd6e4e519a21a079e2a74e50fddaf03e80be22711b92eb4cd410173abea", [:mix], [], "hexpm"},
"deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm"},
"dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], []},
"distillery": {:hex, :distillery, "2.0.12", "6e78fe042df82610ac3fa50bd7d2d8190ad287d120d3cd1682d83a44e8b34dfb", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
"earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm"},
- "ecto": {:hex, :ecto, "3.0.7", "44dda84ac6b17bbbdeb8ac5dfef08b7da253b37a453c34ab1a98de7f7e5fec7f", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
- "ecto_sql": {:hex, :ecto_sql, "3.0.4", "e7a0feb0b2484b90981c56d5cd03c52122c1c31ded0b95ed213b7c5c07ae6737", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0.6", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.3.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
+ "ecto": {:hex, :ecto, "3.1.7", "fa21d06ef56cdc2fdaa62574e8c3ba34a2751d44ea34c30bc65f0728421043e5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
+ "ecto_sql": {:hex, :ecto_sql, "3.1.6", "1e80e30d16138a729c717f73dcb938590bcdb3a4502f3012414d0cbb261045d8", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0 or ~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.2", "332c649d08c18bc1ecc73b1befc68c647136de4f340b548844efc796405743bf", [:mix], [], "hexpm"},
"ex_abi": {:hex, :ex_abi, "0.1.18", "19db9bffdd201edbdff97d7dd5849291218b17beda045c1b76bff5248964f37d", [:mix], [{:exth_crypto, "~> 0.1.4", [hex: :exth_crypto, repo: "hexpm", optional: false]}], "hexpm"},
- "ex_cldr": {:hex, :ex_cldr, "1.3.2", "8f4a00c99d1c537b8e8db7e7903f4bd78d82a7289502d080f70365392b13921b", [:mix], [{:abnf2, "~> 0.1", [hex: :abnf2, optional: false]}, {:decimal, "~> 1.4", [hex: :decimal, optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, optional: true]}, {:poison, "~> 2.1 or ~> 3.0", [hex: :poison, optional: true]}]},
- "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "1.2.0", "ef27299922da913ffad1ed296cacf28b6452fc1243b77301dc17c03276c6ee34", [:mix], [{:decimal, "~> 1.4", [hex: :decimal, optional: false]}, {:ex_cldr, "~> 1.3", [hex: :ex_cldr, optional: false]}, {:poison, "~> 2.1 or ~> 3.1", [hex: :poison, optional: false]}]},
- "ex_cldr_units": {:hex, :ex_cldr_units, "1.1.1", "b3c7256709bdeb3740a5f64ce2bce659eb9cf4cc1afb4cf94aba033b4a18bc5f", [:mix], [{:ex_cldr, "~> 1.0", [hex: :ex_cldr, optional: false]}, {:ex_cldr_numbers, "~> 1.0", [hex: :ex_cldr_numbers, optional: false]}]},
+ "ex_cldr": {:hex, :ex_cldr, "2.7.2", "d79a1af6ed12630a15175d2b88d4381b22db5d6f835c5da8de132f0cf712b233", [:mix], [{:cldr_utils, "~> 2.1", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
+ "ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.3.0", "bffae489416b8b05d4683403263f5d62aae17de70c24ff915a533541fea514de", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
+ "ex_cldr_lists": {:hex, :ex_cldr_lists, "2.2.0", "b99f8752d098fc6ba5f083bbd0b25d0d01e36b0042155cf6abd5f205306ba849", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.6", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
+ "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.6.4", "5b1ac8451f889576bb29dee70412de1170974298727ab944aa4d17e91bdd3472", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.3", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
+ "ex_cldr_units": {:hex, :ex_cldr_units, "2.5.1", "0e65067a22a7c5146266c313d6333c2700868c32aa6d536f47c6c0d84aac3ac1", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.2", [hex: :ex_cldr_lists, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.6", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.19.2", "6f4081ccd9ed081b6dc0bd5af97a41e87f5554de469e7d76025fba535180565f", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
- "ex_machina": {:hex, :ex_machina, "2.2.2", "d84217a6fb7840ff771d2561b8aa6d74a0d8968e4b10ecc0d7e9890dc8fb1c6a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
+ "ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
"ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
"ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"},
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []},
@@ -53,10 +56,10 @@
"flow": {:hex, :flow, "0.14.3", "0d92991fe53035894d24aa8dec10dcfccf0ae00c4ed436ace3efa9813a646902", [:mix], [{:gen_stage, "~> 0.14.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm"},
"gen_stage": {:hex, :gen_stage, "0.14.1", "9d46723fda072d4f4bb31a102560013f7960f5d80ea44dcb96fd6304ed61e7a4", [:mix], [], "hexpm"},
"gettext": {:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2", [:mix], [], "hexpm"},
- "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
+ "hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], []},
"httpoison": {:hex, :httpoison, "1.5.0", "71ae9f304bdf7f00e9cd1823f275c955bdfc68282bc5eb5c85c3a9ade865d68e", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
- "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
+ "idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], []},
"junit_formatter": {:hex, :junit_formatter, "3.0.0", "13950d944dbd295da7d8cc4798b8faee808a8bb9b637c88069954eac078ac9da", [:mix], [], "hexpm"},
@@ -70,7 +73,7 @@
"memento": {:hex, :memento, "0.3.1", "b2909390820550d8b90b68ec96f9e15ff8a45a28b6f97fa4a62ef50e87c2f9d9", [:mix], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
- "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
+ "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
"mix_erlang_tasks": {:hex, :mix_erlang_tasks, "0.1.0", "36819fec60b80689eb1380938675af215565a89320a9e29c72c70d97512e4649", [:mix], [], "hexpm"},
"mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
"mock": {:hex, :mock, "0.3.2", "e98e998fd76c191c7e1a9557c8617912c53df3d4a6132f561eb762b699ef59fa", [:mix], [{:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
@@ -80,21 +83,21 @@
"nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"},
"optimal": {:hex, :optimal, "0.3.6", "46bbf52fbbbd238cda81e02560caa84f93a53c75620f1fe19e81e4ae7b07d1dd", [:mix], [], "hexpm"},
"parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], []},
- "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
+ "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.4.0", "56fe9a809e0e735f3e3b9b31c1b749d4b436e466d8da627b8d82f90eaae714d2", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_form_awesomplete": {:hex, :phoenix_form_awesomplete, "0.1.4", "4af0603d8d41ca638e70f74d6defff331e4db106dd85f75f125579ca27bd8b64", [:mix], [{:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.13.1", "fa8f034b5328e2dfa0e4131b5569379003f34bc1fafdaa84985b0b9d2f12e68b", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.0", "3bb31a9fbd40ffe8652e60c8660dffd72dd231efcdf49b744fb75b9ef7db5dd2", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.1", "6668d787e602981f24f17a5fbb69cc98f8ab085114ebfac6cc36e10a90c8e93c", [:mix], [], "hexpm"},
- "plug": {:hex, :plug, "1.7.2", "d7b7db7fbd755e8283b6c0a50be71ec0a3d67d9213d74422d9372effc8e87fd1", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}], "hexpm"},
+ "plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
"plug_cowboy": {:hex, :plug_cowboy, "2.0.1", "d798f8ee5acc86b7d42dbe4450b8b0dadf665ce588236eb0a751a132417a980e", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"},
- "postgrex": {:hex, :postgrex, "0.14.1", "63247d4a5ad6b9de57a0bac5d807e1c32d41e39c04b8a4156a26c63bcd8a2e49", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
+ "postgrex": {:hex, :postgrex, "0.15.0", "dd5349161019caeea93efa42f9b22f9d79995c3a86bdffb796427b4c9863b0f0", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"prometheus": {:hex, :prometheus, "4.2.0", "06c58bfdfe28d3168b926da614cb9a6d39593deebde648a5480e32dfa3c370e9", [:mix, :rebar3], [], "hexpm"},
- "prometheus_ecto": {:git, "https://github.com/deadtrickster/prometheus-ecto.git", "650a403183f6a2fb6b682d7fbcba8bf9d24fe1e4", [ref: "650a403183f6a2fb6b682d7fbcba8bf9d24fe1e4"]},
+ "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
"prometheus_ex": {:hex, :prometheus_ex, "3.0.3", "5d722263bb1f7a9b1d02554de42e61ea672b4e3c07c3f74e23ce35ab5e111cfa", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
"prometheus_phoenix": {:hex, :prometheus_phoenix, "1.2.1", "964a74dfbc055f781d3a75631e06ce3816a2913976d1df7830283aa3118a797a", [:mix], [{:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
@@ -108,11 +111,11 @@
"spandex_datadog": {:hex, :spandex_datadog, "0.4.0", "75113a73e843123074886a2e31994af07d6e0632749a8d97e9ca6157b120c287", [:mix], [{:msgpax, "~> 2.2.1", [hex: :msgpax, repo: "hexpm", optional: false]}, {:spandex, "~> 2.3", [hex: :spandex, repo: "hexpm", optional: false]}], "hexpm"},
"spandex_ecto": {:hex, :spandex_ecto, "0.4.0", "deaeaddc11a35f1c551206c53d09bb93a0da5808dbef751430e465c8c7de01d3", [:mix], [{:spandex, "~> 2.2", [hex: :spandex, repo: "hexpm", optional: false]}], "hexpm"},
"spandex_phoenix": {:hex, :spandex_phoenix, "0.3.1", "9cb9a4a9f2161f171d9df9afa1289a0d037abbbeecabae674f959b57f106f201", [:mix], [{:plug, "~> 1.3", [hex: :plug, repo: "hexpm", optional: false]}, {:spandex, "~> 2.2", [hex: :spandex, repo: "hexpm", optional: false]}], "hexpm"},
- "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
- "telemetry": {:hex, :telemetry, "0.3.0", "099a7f3ce31e4780f971b4630a3c22ec66d22208bc090fe33a2a3a6a67754a73", [:rebar3], [], "hexpm"},
- "timex": {:hex, :timex, "3.5.0", "b0a23167da02d0fe4f1a4e104d1f929a00d348502b52432c05de875d0b9cffa5", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
- "tzdata": {:hex, :tzdata, "0.5.19", "7962a3997bf06303b7d1772988ede22260f3dae1bf897408ebdac2b4435f4e6a", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
- "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
+ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
+ "telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
+ "timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
+ "tzdata": {:hex, :tzdata, "1.0.1", "f6027a331af7d837471248e62733c6ebee86a72e57c613aa071ebb1f750fc71a", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
+ "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
"wallaby": {:hex, :wallaby, "0.22.0", "e5d16bfa7ab23562c8a6e3b0a31445a2fd470ca622082a910114807ba823780d", [:mix], [{:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, ">= 1.4.0", [hex: :poison, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm"},
"websocket_client": {:hex, :websocket_client, "1.3.0", "2275d7daaa1cdacebf2068891c9844b15f4fdc3de3ec2602420c2fb486db59b6", [:rebar3], [], "hexpm"},
"wobserver": {:git, "https://github.com/poanetwork/wobserver.git", "13bcda30a87f4f0be1878920a79433ad831eefbe", [branch: "support-https"]},
diff --git a/rel/commands/clear_build.sh b/rel/commands/clear_build.sh
index 5faca7ffeb..a07a11870e 100755
--- a/rel/commands/clear_build.sh
+++ b/rel/commands/clear_build.sh
@@ -2,11 +2,13 @@
rm -rf ./_build
rm -rf ./deps
-rm -rf ./logs/dev
-rm -rf ./apps/explorer/node_modules
-rm -rf ./apps/block_scout_web/assets/node_modules
+logs=$(find . -not -path '*/\.*' -name "logs" -type d)
+dev=$(find ${logs} -name "dev")
+rm -rf {ls -la ${dev}}
+
+find . -name "node_modules" -type d -exec rm -rf '{}' +
case "$1" in
-f)
rm -rf ./apps/block_scout_web/priv/static;;
-esac
\ No newline at end of file
+esac