merge master

pull/2433/head
saneery 5 years ago
commit 1cdaa4f452
  1. 2
      .credo.exs
  2. 10
      CHANGELOG.md
  3. 213
      apps/block_scout_web/assets/css/theme/_dark-theme.scss
  4. 637
      apps/block_scout_web/assets/js/lib/awesomplete-util.js
  5. 2
      apps/block_scout_web/assets/js/lib/awesomplete.js
  6. 3099
      apps/block_scout_web/assets/package-lock.json
  7. 9
      apps/block_scout_web/assets/package.json
  8. 44
      apps/block_scout_web/assets/webpack.config.js
  9. 3
      apps/block_scout_web/config/config.exs
  10. 2
      apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
  11. 12
      apps/block_scout_web/lib/block_scout_web/cldr.ex
  12. 4
      apps/block_scout_web/lib/block_scout_web/csp_header.ex
  13. 2
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  14. 2
      apps/block_scout_web/lib/block_scout_web/schema/types.ex
  15. 4
      apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
  16. 10
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
  17. 16
      apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex
  18. 6
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  19. 4
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  20. 4
      apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
  21. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_tile.html.eex
  22. 2
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_token_transfer.html.eex
  23. 2
      apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
  24. 10
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
  25. 2
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  26. 2
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/stats_view.ex
  27. 6
      apps/block_scout_web/lib/block_scout_web/views/block_view.ex
  28. 8
      apps/block_scout_web/lib/block_scout_web/views/cldr_helper/number.ex
  29. 2
      apps/block_scout_web/lib/block_scout_web/views/currency_helpers.ex
  30. 4
      apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex
  31. 25
      apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
  32. 6
      apps/block_scout_web/lib/block_scout_web/views/wei_helpers.ex
  33. 7
      apps/block_scout_web/mix.exs
  34. 3
      apps/block_scout_web/package-lock.json
  35. 126
      apps/block_scout_web/priv/gettext/default.pot
  36. 126
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  37. 16
      apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs
  38. 2
      apps/explorer/lib/explorer/chain.ex
  39. 11
      apps/explorer/mix.exs
  40. 3
      apps/explorer/priv/repo/migrations/20181108205650_additional_internal_transaction_constraints.exs
  41. 75
      apps/explorer/priv/repo/migrations/scripts/20181108205650_large_additional_internal_transaction_constraints.sql
  42. 9
      apps/indexer/lib/indexer/block/catchup/bound_interval_supervisor.ex
  43. 2
      apps/indexer/lib/indexer/block/catchup/fetcher.ex
  44. 23
      mix.lock

@ -89,7 +89,7 @@
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`. # set the `excluded_macros` parameter to `[:schema, :setup, :test]`.
# #
{Credo.Check.Design.DuplicatedCode, false}, {Credo.Check.Design.DuplicatedCode, excluded_macros: [], mass_threshold: 80},
# You can also customize the exit_status of each check. # You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just # If you don't want TODO comments to cause `mix credo` to fail, just

@ -2,21 +2,31 @@
### Features ### Features
- [#2433](https://github.com/poanetwork/blockscout/pull/2433) - Add a functionality to try Eth RPC methods in the documentation - [#2433](https://github.com/poanetwork/blockscout/pull/2433) - Add a functionality to try Eth RPC methods in the documentation
- [#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 - [#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 - [#2456](https://github.com/poanetwork/blockscout/pull/2456) - fetch pending transactions for geth
### Fixes ### Fixes
- [#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 - [#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 - [#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 - [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB
### Chore ### Chore
- [#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 - [#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 - [#2432](https://github.com/poanetwork/blockscout/pull/2432) - bump credo version
- [#2457](https://github.com/poanetwork/blockscout/pull/2457) - update mix.lock - [#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 - [#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 - [#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 - [#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 ## 2.0.2-beta

@ -464,7 +464,220 @@ $labels-dark: #8a8dba; // header nav, labels
// dark text // dark text
.text-dark { .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; 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;
}
} }

@ -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('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
}
// 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 <HTML> 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, '<mark>$&</mark>')
}
// 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 <HTML> 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(/<p>/)
arr[0] = _mark(arr[0], input)
text = arr.join('<p>')
}
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: '<root path>', value: '<value property>', label: '<label property>'})
jsonFlatten: function (data) {
// start json tree recursion
return _jsonFlatten({}, data, '', 0, this)
}
}
}())

@ -0,0 +1,2 @@
import 'awesomplete/awesomplete.css'
import 'awesomplete'

File diff suppressed because it is too large Load Diff

@ -20,12 +20,13 @@
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.1.0-4", "@fortawesome/fontawesome-free": "^5.1.0-4",
"highlight.js": "^9.13.1", "awesomplete": "1.1.2",
"highlightjs-solidity": "^1.0.6",
"bignumber.js": "^7.2.1", "bignumber.js": "^7.2.1",
"bootstrap": "^4.1.3", "bootstrap": "^4.1.3",
"chart.js": "^2.7.2", "chart.js": "^2.7.2",
"clipboard": "^2.0.1", "clipboard": "^2.0.1",
"highlight.js": "^9.13.1",
"highlightjs-solidity": "^1.0.6",
"humps": "^2.0.1", "humps": "^2.0.1",
"jquery": "^3.3.1", "jquery": "^3.3.1",
"lodash": "^4.17.11", "lodash": "^4.17.11",
@ -47,7 +48,7 @@
"babel-loader": "^7.1.4", "babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",
"copy-webpack-plugin": "^4.5.1", "copy-webpack-plugin": "^4.5.1",
"css-loader": "^0.28.11", "css-loader": "^3.1.0",
"eslint": "^4.15.0", "eslint": "^4.15.0",
"eslint-config-standard": "^11.0.0-beta.0", "eslint-config-standard": "^11.0.0-beta.0",
"eslint-plugin-import": "^2.8.0", "eslint-plugin-import": "^2.8.0",
@ -60,7 +61,7 @@
"node-sass": "^4.9.3", "node-sass": "^4.9.3",
"optimize-css-assets-webpack-plugin": "^5.0.3", "optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^2.1.4", "postcss-loader": "^2.1.4",
"sass-loader": "^7.0.1", "sass-loader": "^7.1.0",
"style-loader": "^0.21.0", "style-loader": "^0.21.0",
"terser-webpack-plugin": "^1.3.0", "terser-webpack-plugin": "^1.3.0",
"webpack": "^4.6.0", "webpack": "^4.6.0",

@ -27,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 = const appJs =
{ {
entry: './js/app.js', entry: './js/app.js',
@ -35,7 +75,7 @@ const appJs =
path: path.resolve(__dirname, '../priv/static/js') path: path.resolve(__dirname, '../priv/static/js')
}, },
optimization: { optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})], minimizer: [new TerserJSPlugin(jsOptimizationParams), new OptimizeCSSAssetsPlugin({})],
}, },
module: { module: {
rules: [ rules: [
@ -89,4 +129,4 @@ const appJs =
const viewScripts = glob.sync('./js/view_specific/**/*.js').map(transpileViewScript); const viewScripts = glob.sync('./js/view_specific/**/*.js').map(transpileViewScript);
module.exports = viewScripts.concat(appJs); module.exports = viewScripts.concat(appJs, awesompleteJs);

@ -58,8 +58,7 @@ config :block_scout_web, BlockScoutWeb.SocialMedia,
config :ex_cldr, config :ex_cldr,
default_locale: "en", default_locale: "en",
locales: ["en"], default_backend: BlockScoutWeb.Cldr
gettext: BlockScoutWeb.Gettext
config :logger, :block_scout_web, config :logger, :block_scout_web,
# keep synced with `config/config.exs` # keep synced with `config/config.exs`

@ -73,7 +73,7 @@ defmodule BlockScoutWeb.AddressChannel do
def handle_out("count", %{count: count}, socket) do def handle_out("count", %{count: count}, socket) do
Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale) 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} {:noreply, socket}
end end

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

@ -13,8 +13,8 @@ defmodule BlockScoutWeb.CSPHeader do
"content-security-policy" => "\ "content-security-policy" => "\
connect-src 'self' #{websocket_endpoints(conn)}; \ connect-src 'self' #{websocket_endpoints(conn)}; \
default-src 'self';\ default-src 'self';\
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://nico-amsterdam.github.io;\ script-src 'self' 'unsafe-inline' 'unsafe-eval';\
style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com https://nico-amsterdam.github.io;\ style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com;\
img-src 'self' 'unsafe-inline' 'unsafe-eval' data:;\ img-src 'self' 'unsafe-inline' 'unsafe-eval' data:;\
font-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.gstatic.com data:;\ font-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.gstatic.com data:;\
" "

@ -126,7 +126,7 @@ defmodule BlockScoutWeb.Notifier do
""" """
def broadcast_blocks_indexed_ratio(ratio, finished?) do def broadcast_blocks_indexed_ratio(ratio, finished?) do
Endpoint.broadcast("blocks:indexing", "index_status", %{ Endpoint.broadcast("blocks:indexing", "index_status", %{
ratio: ratio, ratio: Decimal.to_string(ratio),
finished: finished? finished: finished?
}) })
end end

@ -137,7 +137,7 @@ defmodule BlockScoutWeb.Schema.Types do
field(:r, :decimal) field(:r, :decimal)
field(:s, :decimal) field(:s, :decimal)
field(:status, :status) field(:status, :status)
field(:v, :integer) field(:v, :decimal)
field(:value, :wei) field(:value, :wei)
field(:from_address_hash, :address_hash) field(:from_address_hash, :address_hash)
field(:to_address_hash, :address_hash) field(:to_address_hash, :address_hash)

@ -79,7 +79,7 @@
<%= gettext("Incoming Transactions") %> <%= gettext("Incoming Transactions") %>
<% else %> <% else %>
<span data-selector="transaction-count"> <span data-selector="transaction-count">
<%= Cldr.Number.to_string!(@transaction_count, format: "#,###") %> <%= BlockScoutWeb.Cldr.Number.to_string!(@transaction_count, format: "#,###") %>
</span> </span>
<%= gettext("Transactions Sent") %> <%= gettext("Transactions Sent") %>
<% end %> <% end %>
@ -92,7 +92,7 @@
<%= if validator?(@validation_count) do %> <%= if validator?(@validation_count) do %>
<span class="address-detail-item"> <span class="address-detail-item">
<span data-selector="validation-count"> <span data-selector="validation-count">
<%= Cldr.Number.to_string!(@validation_count, format: "#,###") %> <%= BlockScoutWeb.Cldr.Number.to_string!(@validation_count, format: "#,###") %>
</span> </span>
<%= gettext("Blocks Validated") %> <%= gettext("Blocks Validated") %>
</span> </span>

@ -11,10 +11,10 @@
) %> ) %>
</h3> </h3>
</dd> </dd>
<dt class="col-md-2"><%= gettext "Decoded" %></dt>
<dd class="col-md-10">
<%= case decode(@log, @log.transaction) do %> <%= case decode(@log, @log.transaction) do %>
<% {:error, :contract_not_verified} -> %> <% {:error, :contract_not_verified} -> %>
<dt class="col-md-2"><%= gettext "Decoded" %></dt>
<dd class="col-md-10">
<div class="alert alert-info"> <div class="alert alert-info">
<%= gettext "To see decoded input data, the contract must be verified." %> <%= gettext "To see decoded input data, the contract must be verified." %>
<%= case @log.transaction do %> <%= case @log.transaction do %>
@ -25,10 +25,14 @@
<% end %> <% end %>
</div> </div>
<% {:error, :could_not_decode} -> %> <% {:error, :could_not_decode} -> %>
<dt class="col-md-2"><%= gettext "Decoded" %></dt>
<dd class="col-md-10">
<div class="alert alert-danger"> <div class="alert alert-danger">
<%= gettext "Failed to decode log data." %> <%= gettext "Failed to decode log data." %>
</div> </div>
<% {:ok, method_id, text, mapping} -> %> <% {:ok, method_id, text, mapping} -> %>
<dt class="col-md-2"><%= gettext "Decoded" %></dt>
<dd class="col-md-10">
<table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table"> <table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table">
<tr> <tr>
<td>Method Id</td> <td>Method Id</td>
@ -78,7 +82,7 @@
<% end %> <% end %>
</table> </table>
</div> </div>
<% _ -> %> <% _ -> %>
<%= nil %> <%= nil %>
<% end %> <% end %>
<dt class="col-md-2"><%= gettext "Topics" %></dt> <dt class="col-md-2"><%= gettext "Topics" %></dt>

@ -57,7 +57,7 @@
<dl class="row"> <dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Difficulty" %></dt> <dt class="col-sm-3 text-muted"><%= gettext "Difficulty" %></dt>
<dd class="col-sm-9"> <dd class="col-sm-9">
<span><%= @block.difficulty |> Cldr.Number.to_string! %></span> <span><%= @block.difficulty |> BlockScoutWeb.Cldr.Number.to_string! %></span>
</dd> </dd>
</dl> </dl>
@ -65,7 +65,7 @@
<!-- Total Difficulty --> <!-- Total Difficulty -->
<dl class="row"> <dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Total Difficulty" %></dt> <dt class="col-sm-3 text-muted"><%= gettext "Total Difficulty" %></dt>
<dd class="col-sm-9"><span><%= @block.total_difficulty |> Cldr.Number.to_string! %></span></dd> <dd class="col-sm-9"><span><%= @block.total_difficulty |> BlockScoutWeb.Cldr.Number.to_string! %></span></dd>
</dl> </dl>
<!-- Nonce --> <!-- Nonce -->
@ -97,14 +97,14 @@
<dl class="row"> <dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Gas Used" %></dt> <dt class="col-sm-3 text-muted"><%= gettext "Gas Used" %></dt>
<dd class="col-sm-9"> <dd class="col-sm-9">
<span><%= @block.gas_used |> Cldr.Number.to_string! %></span> <span><%= @block.gas_used |> BlockScoutWeb.Cldr.Number.to_string! %></span>
<span class="text-muted">(<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> Cldr.Number.to_string!(format: "#.#%") %>)</span> <span class="text-muted">(<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> BlockScoutWeb.Cldr.Number.to_string!(format: "#.#%") %>)</span>
</dt> </dt>
</dl> </dl>
<dl class="row mb-0"> <dl class="row mb-0">
<dt class="col-sm-3 text-muted"><%= gettext "Gas Limit" %></dt> <dt class="col-sm-3 text-muted"><%= gettext "Gas Limit" %></dt>
<dd class="col-sm-9"> <dd class="col-sm-9">
<span><%= Cldr.Number.to_string!(@block.gas_limit) %></span> <span><%= BlockScoutWeb.Cldr.Number.to_string!(@block.gas_limit) %></span>
</dd> </dd>
</dl> </dl>
<% end %> <% end %>
@ -146,10 +146,10 @@
<h2 class="card-title balance-card-title"><%= gettext "Gas Used" %></h2> <h2 class="card-title balance-card-title"><%= gettext "Gas Used" %></h2>
<div class="text-right"> <div class="text-right">
<h3 class="address-balance-text"> <h3 class="address-balance-text">
<%= @block.gas_used |> Cldr.Number.to_string! %> <%= @block.gas_used |> BlockScoutWeb.Cldr.Number.to_string! %>
<span class="text-muted">(<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> Cldr.Number.to_string!(format: "#.#%") %>)</span> <span class="text-muted">(<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> BlockScoutWeb.Cldr.Number.to_string!(format: "#.#%") %>)</span>
</h3> </h3>
<p class="address-current-balance"><%= @block.gas_limit |> Cldr.Number.to_string! %><%= gettext "Gas Limit" %></p> <p class="address-current-balance"><%= @block.gas_limit |> BlockScoutWeb.Cldr.Number.to_string! %><%= gettext "Gas Limit" %></p>
</div> </div>
<% end %> <% end %>
</div> </div>

@ -56,7 +56,7 @@
<%= gettext "Total transactions" %> <%= gettext "Total transactions" %>
</span> </span>
<span class="dashboard-banner-network-stats-value" data-selector="transaction-count"> <span class="dashboard-banner-network-stats-value" data-selector="transaction-count">
<%= Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %> <%= BlockScoutWeb.Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %>
</span> </span>
</div> </div>
<div class="dashboard-banner-network-stats-item dashboard-banner-network-stats-item-3"> <div class="dashboard-banner-network-stats-item dashboard-banner-network-stats-item-3">
@ -64,7 +64,7 @@
<%= gettext "Total blocks" %> <%= gettext "Total blocks" %>
</span> </span>
<span class="dashboard-banner-network-stats-value" data-selector="block-count"> <span class="dashboard-banner-network-stats-value" data-selector="block-count">
<%= Cldr.Number.to_string!(@block_count, format: "#,###") %> <%= BlockScoutWeb.Cldr.Number.to_string!(@block_count, format: "#,###") %>
</span> </span>
</div> </div>
<div class="dashboard-banner-network-stats-item dashboard-banner-network-stats-item-4"> <div class="dashboard-banner-network-stats-item dashboard-banner-network-stats-item-4">
@ -72,7 +72,7 @@
<%= gettext "Wallet addresses" %> <%= gettext "Wallet addresses" %>
</span> </span>
<span class="dashboard-banner-network-stats-value" data-selector="address-count"> <span class="dashboard-banner-network-stats-value" data-selector="address-count">
<%= Cldr.Number.to_string!(@address_count, format: "#,###") %> <%= BlockScoutWeb.Cldr.Number.to_string!(@address_count, format: "#,###") %>
</span> </span>
</div> </div>
</div> </div>

@ -1,3 +1,7 @@
<link rel="preload" href="/css/awesomplete.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/awesomplete.css"></noscript>
<script src="/js/awesomplete.min.js"></script>
<script src="/js/awesomplete-util.min.js"></script>
<nav class="navbar navbar-dark navbar-expand-lg navbar-primary" data-selector="navbar" id="top-navbar"> <nav class="navbar navbar-dark navbar-expand-lg navbar-primary" data-selector="navbar" id="top-navbar">
<script> <script>
if (localStorage.getItem("current-color-mode") === "dark") { if (localStorage.getItem("current-color-mode") === "dark") {

@ -16,10 +16,6 @@
<meta name="msapplication-config" content="<%= static_path(@conn, "/browserconfig.xml") %>"> <meta name="msapplication-config" content="<%= static_path(@conn, "/browserconfig.xml") %>">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="https://nico-amsterdam.github.io/awesomplete-util/css/awesomplete.css">
<script src="https://nico-amsterdam.github.io/awesomplete-util/js/awesomplete.min.js"></script>
<script src="https://nico-amsterdam.github.io/awesomplete-util/js/awesomplete-util.min.js"></script>
<%= render_existing(@view_module, "_metatags.html", assigns) || render("_default_title.html") %> <%= render_existing(@view_module, "_metatags.html", assigns) || render("_default_title.html") %>
</head> </head>

@ -26,11 +26,11 @@
</span> </span>
<span class="d-flex flex-md-row flex-column mt-3 mt-md-0"> <span class="d-flex flex-md-row flex-column mt-3 mt-md-0">
<span class="tile-title"> <span class="tile-title">
<%= value(@transaction, include_label: false) %> <%= value(@transaction, include_label: false) %>&nbsp;
<%= gettext "Ether" %> <%= gettext "Ether" %>
</span> </span>
<span class="ml-0 ml-md-1 text-nowrap"> <span class="ml-0 ml-md-1 text-nowrap">
<%= formatted_fee(@transaction, denomination: :ether, include_label: false) %> <%= formatted_fee(@transaction, denomination: :ether, include_label: false) %>
<%= gettext "TX Fee" %> <%= gettext "TX Fee" %>
</span> </span>
</span> </span>

@ -19,7 +19,7 @@
<%= @token_transfer |> BlockScoutWeb.AddressView.address_partial_selector(:to, @address, true) |> BlockScoutWeb.RenderHelpers.render_partial() %> <%= @token_transfer |> BlockScoutWeb.AddressView.address_partial_selector(:to, @address, true) |> BlockScoutWeb.RenderHelpers.render_partial() %>
</span> </span>
</span> </span>
<span class="col-xs-12 col-lg-4 ml-3 ml-sm-0"> <span class="col-xs-12 col-lg-4 ml-3 ml-sm-0 text-truncate">
<%= token_transfer_amount(@token_transfer) %> <%= token_transfer_amount(@token_transfer) %>
<%= link(token_symbol(@token_transfer.token), to: token_path(BlockScoutWeb.Endpoint, :show, @token_transfer.token.contract_address_hash)) %> <%= link(token_symbol(@token_transfer.token), to: token_path(BlockScoutWeb.Endpoint, :show, @token_transfer.token.contract_address_hash)) %>
</span> </span>

@ -177,7 +177,7 @@
<div class="card-body card-body-flex-column-space-between"> <div class="card-body card-body-flex-column-space-between">
<h2 class="card-title balance-card-title"><%= token_type_name(type)%><%= gettext " Token Transfer" %></h2> <h2 class="card-title balance-card-title"><%= token_type_name(type)%><%= gettext " Token Transfer" %></h2>
<div class="text-right"> <div class="text-right">
<%= for transfer <- transaction_with_transfers.token_transfers do %> <%= for transfer <- aggregate_token_transfers(transaction_with_transfers.token_transfers) do %>
<h3 class="address-balance-text"> <h3 class="address-balance-text">
<%= token_transfer_amount(transfer) %> <%= token_transfer_amount(transfer) %>

@ -11,10 +11,10 @@
) %> ) %>
</h3> </h3>
</dd> </dd>
<dt class="col-md-1"><%= gettext "Decoded" %></dt>
<dd class="col-md-11">
<%= case decode(@log, @transaction) do %> <%= case decode(@log, @transaction) do %>
<% {:error, :contract_not_verified} -> %> <% {:error, :contract_not_verified} -> %>
<dt class="col-md-1"><%= gettext "Decoded" %></dt>
<dd class="col-md-11">
<div class="alert alert-info"> <div class="alert alert-info">
<%= gettext "To see decoded input data, the contract must be verified." %> <%= gettext "To see decoded input data, the contract must be verified." %>
<%= case @transaction do %> <%= case @transaction do %>
@ -25,10 +25,16 @@
<% end %> <% end %>
</div> </div>
<% {:error, :could_not_decode} -> %> <% {:error, :could_not_decode} -> %>
<dt class="col-md-1"><%= gettext "Decoded" %></dt>
<dd class="col-md-11">
<div class="alert alert-danger"> <div class="alert alert-danger">
<%= gettext "Failed to decode log data." %> <%= gettext "Failed to decode log data." %>
</div> </div>
<% {:error, :no_matching_function} -> %>
<%= nil %>
<% {:ok, method_id, text, mapping} -> %> <% {:ok, method_id, text, mapping} -> %>
<dt class="col-md-1"><%= gettext "Decoded" %></dt>
<dd class="col-md-11">
<table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table"> <table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table">
<tr> <tr>
<td>Method Id</td> <td>Method Id</td>

@ -222,7 +222,7 @@ defmodule BlockScoutWeb.AddressView do
def incoming_transaction_count(address_hash) do def incoming_transaction_count(address_hash) do
address_hash address_hash
|> Chain.address_to_incoming_transaction_count() |> Chain.address_to_incoming_transaction_count()
|> Cldr.Number.to_string!(format: "#,###") |> BlockScoutWeb.Cldr.Number.to_string!(format: "#,###")
end end
def trimmed_hash(%Hash{} = hash) do def trimmed_hash(%Hash{} = hash) do

@ -4,7 +4,7 @@ defmodule BlockScoutWeb.API.RPC.StatsView do
alias BlockScoutWeb.API.RPC.RPCView alias BlockScoutWeb.API.RPC.RPCView
def render("tokensupply.json", token_supply) do 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 end
def render("ethsupply.json", %{total_supply: total_supply}) do def render("ethsupply.json", %{total_supply: total_supply}) do

@ -15,7 +15,7 @@ defmodule BlockScoutWeb.BlockView do
|> Enum.map(&Decimal.to_float(Wei.to(&1.gas_price, :gwei))) |> Enum.map(&Decimal.to_float(Wei.to(&1.gas_price, :gwei)))
|> mean() |> mean()
|> Kernel.||(0) |> Kernel.||(0)
|> Cldr.Number.to_string!() |> BlockScoutWeb.Cldr.Number.to_string!()
unit_text = gettext("Gwei") 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 # 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 case :erlang.phash2(1, 1) do
0 -> 0 ->
Cldr.Unit.to_string!(unit) BlockScoutWeb.Cldr.Unit.to_string!(unit)
1 -> 1 ->
# does not occur # does not occur
@ -42,7 +42,7 @@ defmodule BlockScoutWeb.BlockView do
end end
def formatted_gas(gas, format \\ []) do def formatted_gas(gas, format \\ []) do
Cldr.Number.to_string!(gas, format) BlockScoutWeb.Cldr.Number.to_string!(gas, format)
end end
def formatted_timestamp(%Block{timestamp: timestamp}) do def formatted_timestamp(%Block{timestamp: timestamp}) do

@ -1,4 +1,4 @@
defmodule BlockScoutWeb.Cldr.Number do defmodule BlockScoutWeb.CldrHelper.Number do
@moduledoc """ @moduledoc """
Work-arounds for `Cldr.Number` bugs 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 # 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 case :erlang.phash2(1, 1) do
0 -> 0 ->
Cldr.Number.to_string(decimal, options) BlockScoutWeb.Cldr.Number.to_string(decimal, options)
1 -> 1 ->
# does not occur # 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 # 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 case :erlang.phash2(1, 1) do
0 -> 0 ->
Cldr.Number.to_string!(decimal) BlockScoutWeb.Cldr.Number.to_string!(decimal)
1 -> 1 ->
# does not occur # 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 # 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 case :erlang.phash2(1, 1) do
0 -> 0 ->
Cldr.Number.to_string!(decimal, options) BlockScoutWeb.Cldr.Number.to_string!(decimal, options)
1 -> 1 ->
# does not occur # does not occur

@ -3,7 +3,7 @@ defmodule BlockScoutWeb.CurrencyHelpers do
Helper functions for interacting with `t:BlockScoutWeb.ExchangeRates.USD.t/0` values. Helper functions for interacting with `t:BlockScoutWeb.ExchangeRates.USD.t/0` values.
""" """
alias BlockScoutWeb.Cldr.Number alias BlockScoutWeb.CldrHelper.Number
@doc """ @doc """
Formats the given integer value to a currency format. Formats the given integer value to a currency format.

@ -4,7 +4,7 @@ defmodule BlockScoutWeb.Tokens.Helpers do
""" """
alias BlockScoutWeb.{CurrencyHelpers} alias BlockScoutWeb.{CurrencyHelpers}
alias Explorer.Chain.{Address, Token, TokenTransfer} alias Explorer.Chain.{Address, Token}
@doc """ @doc """
Returns the token transfers' amount according to the token's type and decimals. 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 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. 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) do_token_transfer_amount(token, amount, token_id)
end end

@ -2,7 +2,7 @@ defmodule BlockScoutWeb.TransactionView do
use BlockScoutWeb, :view use BlockScoutWeb, :view
alias BlockScoutWeb.{AddressView, BlockView, TabHelpers} alias BlockScoutWeb.{AddressView, BlockView, TabHelpers}
alias Cldr.Number alias BlockScoutWeb.Cldr.Number
alias Explorer.{Chain, Repo} alias Explorer.{Chain, Repo}
alias Explorer.Chain.Block.Reward alias Explorer.Chain.Block.Reward
alias Explorer.Chain.{Address, Block, InternalTransaction, Transaction, Wei} alias Explorer.Chain.{Address, Block, InternalTransaction, Transaction, Wei}
@ -39,6 +39,25 @@ defmodule BlockScoutWeb.TransactionView do
if type, do: {type, transaction_with_transfers} if type, do: {type, transaction_with_transfers}
end end
def aggregate_token_transfers(token_transfers) do
token_transfers
|> Enum.reduce(%{}, fn token_transfer, acc ->
new_entry = %{
token: token_transfer.token,
amount: token_transfer.amount,
token_id: token_transfer.token_id
}
existing_entry = Map.get(acc, token_transfer.token_contract_address, %{new_entry | amount: Decimal.new(0)})
Map.put(acc, token_transfer.token_contract_address, %{
new_entry
| amount: Decimal.add(new_entry.amount, existing_entry.amount)
})
end)
|> Enum.map(fn {_key, value} -> value end)
end
def token_type_name(type) do def token_type_name(type) do
case type do case type do
:erc20 -> gettext("ERC-20 ") :erc20 -> gettext("ERC-20 ")
@ -100,7 +119,7 @@ defmodule BlockScoutWeb.TransactionView do
%Block{consensus: true} -> %Block{consensus: true} ->
{:ok, confirmations} = Chain.confirmations(block, named_arguments) {:ok, confirmations} = Chain.confirmations(block, named_arguments)
Cldr.Number.to_string!(confirmations, format: "#,###") BlockScoutWeb.Cldr.Number.to_string!(confirmations, format: "#,###")
end end
end end
@ -156,7 +175,7 @@ defmodule BlockScoutWeb.TransactionView do
end end
def gas(%type{gas: gas}) when is_transaction_type(type) do def gas(%type{gas: gas}) when is_transaction_type(type) do
Cldr.Number.to_string!(gas) BlockScoutWeb.Cldr.Number.to_string!(gas)
end end
def skip_decoding?(transaction) do def skip_decoding?(transaction) do

@ -5,7 +5,7 @@ defmodule BlockScoutWeb.WeiHelpers do
import BlockScoutWeb.Gettext import BlockScoutWeb.Gettext
alias BlockScoutWeb.Cldr alias BlockScoutWeb.CldrHelper
alias Explorer.Chain.Wei alias Explorer.Chain.Wei
@valid_units ~w(wei gwei ether)a @valid_units ~w(wei gwei ether)a
@ -60,9 +60,9 @@ defmodule BlockScoutWeb.WeiHelpers do
formatted_value = formatted_value =
if Decimal.cmp(converted_value, 1_000_000_000_000) == :gt do 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 else
Cldr.Number.to_string!(converted_value, format: "#,##0.##################") CldrHelper.Number.to_string!(converted_value, format: "#,##0.##################")
end end
if Keyword.get(options, :include_unit_label, true) do if Keyword.get(options, :include_unit_label, true) do

@ -50,7 +50,6 @@ defmodule BlockScoutWeb.Mixfile do
defp extra_applications, defp extra_applications,
do: [ do: [
:ex_cldr,
:logger, :logger,
:runtime_tools :runtime_tools
] ]
@ -78,8 +77,10 @@ defmodule BlockScoutWeb.Mixfile do
# Need until https://github.com/absinthe-graphql/absinthe_relay/pull/125 is released, then can be removed # 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 # The current `absinthe_relay` is compatible though as shown from that PR
{:ecto, "~> 3.0", override: true}, {:ecto, "~> 3.0", override: true},
{:ex_cldr_numbers, "~> 1.0"}, {:ex_cldr, "~> 2.7"},
{:ex_cldr_units, "~> 1.0"}, {:ex_cldr_numbers, "~> 2.6"},
{:ex_cldr_units, "~> 2.5"},
{:cldr_utils, "~> 2.3"},
{:ex_machina, "~> 2.1", only: [:test]}, {:ex_machina, "~> 2.1", only: [:test]},
# Code coverage # Code coverage
{:excoveralls, "~> 0.10.0", only: [:test], github: "KronicDeth/excoveralls", branch: "circle-workflows"}, {:excoveralls, "~> 0.10.0", only: [:test], github: "KronicDeth/excoveralls", branch: "circle-workflows"},

@ -1,3 +0,0 @@
{
"lockfileVersion": 1
}

@ -49,7 +49,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:144 #: lib/block_scout_web/views/transaction_view.ex:163
msgid "(Awaiting internal transactions for status)" msgid "(Awaiting internal transactions for status)"
msgstr "" msgstr ""
@ -62,7 +62,7 @@ msgid "(query)"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:40 #: 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." msgid "- We're indexing this chain right now. Some of the counts may be inaccurate."
msgstr "" msgstr ""
@ -87,7 +87,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:66 #: lib/block_scout_web/templates/layout/_topnav.html.eex:70
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""
@ -157,7 +157,7 @@ msgid "Block Height: %{height}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:55 #: lib/block_scout_web/templates/layout/app.html.eex:51
msgid "Block Mined, awaiting import..." msgid "Block Mined, awaiting import..."
msgstr "" msgstr ""
@ -178,13 +178,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:87 #: lib/block_scout_web/templates/chain/show.html.eex:87
#: lib/block_scout_web/templates/layout/_topnav.html.eex:26
#: lib/block_scout_web/templates/layout/_topnav.html.eex:30 #: lib/block_scout_web/templates/layout/_topnav.html.eex:30
#: lib/block_scout_web/templates/layout/_topnav.html.eex:34
msgid "Blocks" msgid "Blocks"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:54 #: lib/block_scout_web/templates/layout/app.html.eex:50
msgid "Blocks Indexed" msgid "Blocks Indexed"
msgstr "" msgstr ""
@ -280,12 +280,12 @@ msgid "Contract Address Pending"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:221 #: lib/block_scout_web/views/transaction_view.ex:240
msgid "Contract Call" msgid "Contract Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:220 #: lib/block_scout_web/views/transaction_view.ex:239
msgid "Contract Creation" msgid "Contract Creation"
msgstr "" msgstr ""
@ -364,19 +364,19 @@ msgid "Error trying to fetch balances."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:148 #: lib/block_scout_web/views/transaction_view.ex:167
msgid "Error: %{reason}" msgid "Error: %{reason}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:146 #: lib/block_scout_web/views/transaction_view.ex:165
msgid "Error: (Awaiting internal transactions for reason)" msgid "Error: (Awaiting internal transactions for reason)"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_balance_card.html.eex:15 #: lib/block_scout_web/templates/address/_balance_card.html.eex:15
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21 #: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21
#: lib/block_scout_web/templates/layout/app.html.eex:60 #: 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/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:30 #: lib/block_scout_web/templates/transaction/_tile.html.eex:30
#: lib/block_scout_web/templates/transaction/overview.html.eex:196 #: lib/block_scout_web/templates/transaction/overview.html.eex:196
@ -402,7 +402,7 @@ msgid "Fetching tokens..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:36 #: lib/block_scout_web/templates/layout/_topnav.html.eex:40
msgid "Forked Blocks (Reorgs)" msgid "Forked Blocks (Reorgs)"
msgstr "" msgstr ""
@ -456,7 +456,7 @@ msgid "IN"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:56 #: lib/block_scout_web/templates/layout/app.html.eex:52
msgid "Indexing Tokens" msgid "Indexing Tokens"
msgstr "" msgstr ""
@ -476,7 +476,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11 #: 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/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:306 #: 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:293
msgid "Internal Transactions" msgid "Internal Transactions"
msgstr "" msgstr ""
@ -488,7 +488,7 @@ msgid "Inventory"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:57 #: lib/block_scout_web/templates/layout/app.html.eex:53
msgid "Less than" msgid "Less than"
msgstr "" msgstr ""
@ -503,21 +503,21 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17 #: 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/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:312 #: 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:294
msgid "Logs" msgid "Logs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:31 #: lib/block_scout_web/templates/chain/show.html.eex:31
#: lib/block_scout_web/templates/layout/app.html.eex:58 #: 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
#: lib/block_scout_web/views/address_view.ex:121 #: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap" msgid "Market Cap"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:129 #: lib/block_scout_web/views/transaction_view.ex:148
#: lib/block_scout_web/views/transaction_view.ex:129 #: lib/block_scout_web/views/transaction_view.ex:148
msgid "Max of" msgid "Max of"
msgstr "" msgstr ""
@ -557,11 +557,11 @@ msgid "Must be set to:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:50
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:50 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:50
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:52
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -610,9 +610,9 @@ msgid "Parent Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:54 #: lib/block_scout_web/templates/layout/_topnav.html.eex:58
#: lib/block_scout_web/views/transaction_view.ex:143 #: lib/block_scout_web/views/transaction_view.ex:162
#: lib/block_scout_web/views/transaction_view.ex:177 #: lib/block_scout_web/views/transaction_view.ex:196
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
@ -628,7 +628,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:24 #: lib/block_scout_web/templates/chain/show.html.eex:24
#: lib/block_scout_web/templates/layout/app.html.eex:59 #: lib/block_scout_web/templates/layout/app.html.eex:55
msgid "Price" msgid "Price"
msgstr "" msgstr ""
@ -677,8 +677,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:118 #: lib/block_scout_web/templates/layout/_topnav.html.eex:122
#: lib/block_scout_web/templates/layout/_topnav.html.eex:135 #: lib/block_scout_web/templates/layout/_topnav.html.eex:139
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -702,7 +702,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8 #: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:145 #: lib/block_scout_web/views/transaction_view.ex:164
msgid "Success" msgid "Success"
msgstr "" msgstr ""
@ -783,7 +783,7 @@ msgid "To"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:16 #: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "" msgstr ""
@ -807,7 +807,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5 #: 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/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:238
msgid "Token Transfer" msgid "Token Transfer"
msgstr "" msgstr ""
@ -817,7 +817,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4 #: 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/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35 #: 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:292
msgid "Token Transfers" msgid "Token Transfers"
msgstr "" msgstr ""
@ -851,7 +851,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:3 #: 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:241
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -876,7 +876,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10 #: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:18 #: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: lib/block_scout_web/templates/chain/show.html.eex:108 #: lib/block_scout_web/templates/chain/show.html.eex:108
#: lib/block_scout_web/templates/layout/_topnav.html.eex:45 #: lib/block_scout_web/templates/layout/_topnav.html.eex:49
#: lib/block_scout_web/views/address_view.ex:305 #: lib/block_scout_web/views/address_view.ex:305
msgid "Transactions" msgid "Transactions"
msgstr "" msgstr ""
@ -904,7 +904,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:80 #: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/layout/_topnav.html.eex:33 #: lib/block_scout_web/templates/layout/_topnav.html.eex:37
msgid "Uncles" msgid "Uncles"
msgstr "" msgstr ""
@ -919,7 +919,7 @@ msgid "Used"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:49 #: lib/block_scout_web/templates/layout/_topnav.html.eex:53
msgid "Validated" msgid "Validated"
msgstr "" msgstr ""
@ -1066,17 +1066,17 @@ msgid "Loading...."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:74 #: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:78 #: lib/block_scout_web/templates/layout/_topnav.html.eex:82
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:83 #: lib/block_scout_web/templates/layout/_topnav.html.eex:87
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1126,8 +1126,12 @@ msgid "Static Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14 #: 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" msgid "Decoded"
msgstr "" msgstr ""
@ -1448,8 +1452,8 @@ msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:112
#: lib/block_scout_web/templates/layout/_topnav.html.eex:116 #: 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" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1513,7 +1517,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24 #: 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/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:295
msgid "Raw Trace" msgid "Raw Trace"
msgstr "" msgstr ""
@ -1675,7 +1679,7 @@ msgid "ETH RPC API Documentation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:88 #: lib/block_scout_web/templates/layout/_topnav.html.eex:92
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -1721,12 +1725,12 @@ msgid "Change Network"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:44 #: lib/block_scout_web/views/transaction_view.ex:63
msgid "ERC-20 " msgid "ERC-20 "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:45 #: lib/block_scout_web/views/transaction_view.ex:64
msgid "ERC-721 " msgid "ERC-721 "
msgstr "" msgstr ""
@ -1771,9 +1775,9 @@ msgid "Constructor Arguments"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59 #: 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/_decoded_input_body.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:65
msgid "Copy Value" msgid "Copy Value"
msgstr "" msgstr ""
@ -1783,29 +1787,29 @@ msgid "Create2"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:53
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114 #: 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/_decoded_input_body.html.eex:21
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:55
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:121
msgid "Data" msgid "Data"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:31
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:52
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:54
msgid "Indexed?" msgid "Indexed?"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
msgid "Log Data" msgid "Log Data"
msgstr "" msgstr ""
@ -1817,14 +1821,14 @@ msgid "Reward"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:88
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:91
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47 #: 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/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:53
msgid "Type" msgid "Type"
msgstr "" msgstr ""

@ -49,7 +49,7 @@ msgid "%{subnetwork} Explorer - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:144 #: lib/block_scout_web/views/transaction_view.ex:163
msgid "(Awaiting internal transactions for status)" msgid "(Awaiting internal transactions for status)"
msgstr "" msgstr ""
@ -62,7 +62,7 @@ msgid "(query)"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:40 #: 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." msgid "- We're indexing this chain right now. Some of the counts may be inaccurate."
msgstr "" msgstr ""
@ -87,7 +87,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:66 #: lib/block_scout_web/templates/layout/_topnav.html.eex:70
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""
@ -157,7 +157,7 @@ msgid "Block Height: %{height}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:55 #: lib/block_scout_web/templates/layout/app.html.eex:51
msgid "Block Mined, awaiting import..." msgid "Block Mined, awaiting import..."
msgstr "" msgstr ""
@ -178,13 +178,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:87 #: lib/block_scout_web/templates/chain/show.html.eex:87
#: lib/block_scout_web/templates/layout/_topnav.html.eex:26
#: lib/block_scout_web/templates/layout/_topnav.html.eex:30 #: lib/block_scout_web/templates/layout/_topnav.html.eex:30
#: lib/block_scout_web/templates/layout/_topnav.html.eex:34
msgid "Blocks" msgid "Blocks"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:54 #: lib/block_scout_web/templates/layout/app.html.eex:50
msgid "Blocks Indexed" msgid "Blocks Indexed"
msgstr "" msgstr ""
@ -280,12 +280,12 @@ msgid "Contract Address Pending"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:221 #: lib/block_scout_web/views/transaction_view.ex:240
msgid "Contract Call" msgid "Contract Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:220 #: lib/block_scout_web/views/transaction_view.ex:239
msgid "Contract Creation" msgid "Contract Creation"
msgstr "" msgstr ""
@ -364,19 +364,19 @@ msgid "Error trying to fetch balances."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:148 #: lib/block_scout_web/views/transaction_view.ex:167
msgid "Error: %{reason}" msgid "Error: %{reason}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:146 #: lib/block_scout_web/views/transaction_view.ex:165
msgid "Error: (Awaiting internal transactions for reason)" msgid "Error: (Awaiting internal transactions for reason)"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_balance_card.html.eex:15 #: lib/block_scout_web/templates/address/_balance_card.html.eex:15
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21 #: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21
#: lib/block_scout_web/templates/layout/app.html.eex:60 #: 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/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:30 #: lib/block_scout_web/templates/transaction/_tile.html.eex:30
#: lib/block_scout_web/templates/transaction/overview.html.eex:196 #: lib/block_scout_web/templates/transaction/overview.html.eex:196
@ -402,7 +402,7 @@ msgid "Fetching tokens..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:36 #: lib/block_scout_web/templates/layout/_topnav.html.eex:40
msgid "Forked Blocks (Reorgs)" msgid "Forked Blocks (Reorgs)"
msgstr "" msgstr ""
@ -456,7 +456,7 @@ msgid "IN"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:56 #: lib/block_scout_web/templates/layout/app.html.eex:52
msgid "Indexing Tokens" msgid "Indexing Tokens"
msgstr "" msgstr ""
@ -476,7 +476,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11 #: 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/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:306 #: 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:293
msgid "Internal Transactions" msgid "Internal Transactions"
msgstr "" msgstr ""
@ -488,7 +488,7 @@ msgid "Inventory"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:57 #: lib/block_scout_web/templates/layout/app.html.eex:53
msgid "Less than" msgid "Less than"
msgstr "" msgstr ""
@ -503,21 +503,21 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17 #: 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/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:312 #: 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:294
msgid "Logs" msgid "Logs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:31 #: lib/block_scout_web/templates/chain/show.html.eex:31
#: lib/block_scout_web/templates/layout/app.html.eex:58 #: 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
#: lib/block_scout_web/views/address_view.ex:121 #: lib/block_scout_web/views/address_view.ex:121
msgid "Market Cap" msgid "Market Cap"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:129 #: lib/block_scout_web/views/transaction_view.ex:148
#: lib/block_scout_web/views/transaction_view.ex:129 #: lib/block_scout_web/views/transaction_view.ex:148
msgid "Max of" msgid "Max of"
msgstr "" msgstr ""
@ -557,11 +557,11 @@ msgid "Must be set to:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:50
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:50 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:50
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:52
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -610,9 +610,9 @@ msgid "Parent Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:54 #: lib/block_scout_web/templates/layout/_topnav.html.eex:58
#: lib/block_scout_web/views/transaction_view.ex:143 #: lib/block_scout_web/views/transaction_view.ex:162
#: lib/block_scout_web/views/transaction_view.ex:177 #: lib/block_scout_web/views/transaction_view.ex:196
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
@ -628,7 +628,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:24 #: lib/block_scout_web/templates/chain/show.html.eex:24
#: lib/block_scout_web/templates/layout/app.html.eex:59 #: lib/block_scout_web/templates/layout/app.html.eex:55
msgid "Price" msgid "Price"
msgstr "" msgstr ""
@ -677,8 +677,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:118 #: lib/block_scout_web/templates/layout/_topnav.html.eex:122
#: lib/block_scout_web/templates/layout/_topnav.html.eex:135 #: lib/block_scout_web/templates/layout/_topnav.html.eex:139
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -702,7 +702,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8 #: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:145 #: lib/block_scout_web/views/transaction_view.ex:164
msgid "Success" msgid "Success"
msgstr "" msgstr ""
@ -783,7 +783,7 @@ msgid "To"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:16 #: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "" msgstr ""
@ -807,7 +807,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5 #: 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/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:238
msgid "Token Transfer" msgid "Token Transfer"
msgstr "" msgstr ""
@ -817,7 +817,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4 #: 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/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35 #: 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:292
msgid "Token Transfers" msgid "Token Transfers"
msgstr "" msgstr ""
@ -851,7 +851,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:3 #: 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:241
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -876,7 +876,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10 #: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:18 #: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: lib/block_scout_web/templates/chain/show.html.eex:108 #: lib/block_scout_web/templates/chain/show.html.eex:108
#: lib/block_scout_web/templates/layout/_topnav.html.eex:45 #: lib/block_scout_web/templates/layout/_topnav.html.eex:49
#: lib/block_scout_web/views/address_view.ex:305 #: lib/block_scout_web/views/address_view.ex:305
msgid "Transactions" msgid "Transactions"
msgstr "" msgstr ""
@ -904,7 +904,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:80 #: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/layout/_topnav.html.eex:33 #: lib/block_scout_web/templates/layout/_topnav.html.eex:37
msgid "Uncles" msgid "Uncles"
msgstr "" msgstr ""
@ -919,7 +919,7 @@ msgid "Used"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:49 #: lib/block_scout_web/templates/layout/_topnav.html.eex:53
msgid "Validated" msgid "Validated"
msgstr "" msgstr ""
@ -1066,17 +1066,17 @@ msgid "Loading...."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:74 #: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:78 #: lib/block_scout_web/templates/layout/_topnav.html.eex:82
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:83 #: lib/block_scout_web/templates/layout/_topnav.html.eex:87
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1126,8 +1126,12 @@ msgid "Static Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14 #: 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" msgid "Decoded"
msgstr "" msgstr ""
@ -1449,8 +1453,8 @@ msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:112
#: lib/block_scout_web/templates/layout/_topnav.html.eex:116 #: 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" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1514,7 +1518,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24 #: 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/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:295
msgid "Raw Trace" msgid "Raw Trace"
msgstr "" msgstr ""
@ -1676,7 +1680,7 @@ msgid "ETH RPC API Documentation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:88 #: lib/block_scout_web/templates/layout/_topnav.html.eex:92
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -1722,12 +1726,12 @@ msgid "Change Network"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:44 #: lib/block_scout_web/views/transaction_view.ex:63
msgid "ERC-20 " msgid "ERC-20 "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/views/transaction_view.ex:45 #: lib/block_scout_web/views/transaction_view.ex:64
msgid "ERC-721 " msgid "ERC-721 "
msgstr "" msgstr ""
@ -1772,9 +1776,9 @@ msgid "Constructor Arguments"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59 #: 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/_decoded_input_body.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:65
msgid "Copy Value" msgid "Copy Value"
msgstr "" msgstr ""
@ -1784,29 +1788,29 @@ msgid "Create2"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:53
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114 #: 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/_decoded_input_body.html.eex:21
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:55
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:121
msgid "Data" msgid "Data"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:31
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:52
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:54
msgid "Indexed?" msgid "Indexed?"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
msgid "Log Data" msgid "Log Data"
msgstr "" msgstr ""
@ -1818,14 +1822,14 @@ msgid "Reward"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:88
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:91
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47 #: 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/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:53
msgid "Type" msgid "Type"
msgstr "" msgstr ""

@ -253,4 +253,20 @@ defmodule BlockScoutWeb.TransactionViewTest do
assert TransactionView.current_tab_name(logs_path) == "Logs" assert TransactionView.current_tab_name(logs_path) == "Logs"
end end
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
end
end end

@ -232,7 +232,7 @@ defmodule Explorer.Chain do
address_hash address_hash
|> address_to_transactions_without_rewards(paging_options, options) |> 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 -> |> Enum.sort_by(fn item ->
case item do case item do
{%Reward{} = emission_reward, _} -> {%Reward{} = emission_reward, _} ->

@ -76,7 +76,7 @@ defmodule Explorer.Mixfile do
# `override: true` for `ex_machina` compatibility # `override: true` for `ex_machina` compatibility
{:ecto, "~> 3.0", override: true}, {:ecto, "~> 3.0", override: true},
# Storing blockchain data and derived data in PostgreSQL. # Storing blockchain data and derived data in PostgreSQL.
{:ecto_sql, "~> 3.0"}, {:ecto_sql, "~> 3.1"},
# JSONRPC access to query smart contracts # JSONRPC access to query smart contracts
{:ethereum_jsonrpc, in_umbrella: true}, {:ethereum_jsonrpc, in_umbrella: true},
# Data factory for testing # Data factory for testing
@ -98,12 +98,7 @@ defmodule Explorer.Mixfile do
# For compatibility with `prometheus_process_collector`, which hasn't been updated yet # For compatibility with `prometheus_process_collector`, which hasn't been updated yet
{:prometheus, "~> 4.0", override: true}, {:prometheus, "~> 4.0", override: true},
# Prometheus metrics for query duration # Prometheus metrics for query duration
{ {:prometheus_ecto, "~> 1.4.3"},
:prometheus_ecto,
"~> 1.3",
# Ecto 3.0 compatibility
github: "deadtrickster/prometheus-ecto", ref: "650a403183f6a2fb6b682d7fbcba8bf9d24fe1e4"
},
# bypass optional dependency # bypass optional dependency
{:plug_cowboy, "~> 2.0", only: [:dev, :test]}, {:plug_cowboy, "~> 2.0", only: [:dev, :test]},
{:que, "~> 0.10.1"}, {:que, "~> 0.10.1"},
@ -115,7 +110,7 @@ defmodule Explorer.Mixfile do
# `:spandex` tracing of `:ecto` # `:spandex` tracing of `:ecto`
{:spandex_ecto, "~> 0.4.0"}, {:spandex_ecto, "~> 0.4.0"},
# Attach `:prometheus_ecto` to `:ecto` # Attach `:prometheus_ecto` to `:ecto`
{:telemetry, "~> 0.3.0"}, {:telemetry, "~> 0.4.0"},
# `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0` # `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0`
{:timex, "~> 3.6"}, {:timex, "~> 3.6"},
{:con_cache, "~> 0.13"} {:con_cache, "~> 0.13"}

@ -7,6 +7,9 @@ defmodule Explorer.Repo.Migrations.AdditionalInternalTransactionConstraints do
mix ecto.migrate mix ecto.migrate
psql -d $DATABASE -a -f priv/repo/migrations/scripts/20181108205650_additional_internal_transaction_constraints.sql 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 use Ecto.Migration

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

@ -185,7 +185,12 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisor do
def handle_info( def handle_info(
{ref, {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__{ %__MODULE__{
bound_interval: bound_interval, bound_interval: bound_interval,
task: %Task{ref: ref} task: %Task{ref: ref}
@ -197,7 +202,7 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisor do
0 -> 0 ->
Logger.info("Index already caught up.", Logger.info("Index already caught up.",
first_block_number: first_block_number, first_block_number: first_block_number,
last_block_number: 0, last_block_number: last_block_number,
missing_block_count: 0, missing_block_count: 0,
shrunk: shrunk shrunk: shrunk
) )

@ -123,7 +123,7 @@ defmodule Indexer.Block.Catchup.Fetcher do
Shrinkable.shrunk?(sequence) Shrinkable.shrunk?(sequence)
end 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
end end

@ -15,6 +15,7 @@
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, "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"}, "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.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [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], []}, "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"}, "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"}, "con_cache": {:hex, :con_cache, "0.13.1", "047e097ab2a8c6876e12d0c29e29a86d487b592df97b98e3e2abedad574e215d", [:mix], [], "hexpm"},
@ -25,20 +26,22 @@
"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"}, "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]}]}, "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"}, "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"}, "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"}, "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
"decorator": {:hex, :decorator, "1.3.0", "6203dbd6e4e519a21a079e2a74e50fddaf03e80be22711b92eb4cd410173abea", [:mix], [], "hexpm"}, "decorator": {:hex, :decorator, "1.3.0", "6203dbd6e4e519a21a079e2a74e50fddaf03e80be22711b92eb4cd410173abea", [:mix], [], "hexpm"},
"deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm"}, "deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm"},
"dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], []}, "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"}, "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"}, "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": {: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.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_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"}, "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_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": {: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_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_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_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_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_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.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_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"}, "ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
@ -87,14 +90,14 @@
"phoenix_html": {:hex, :phoenix_html, "2.13.1", "fa8f034b5328e2dfa0e4131b5569379003f34bc1fafdaa84985b0b9d2f12e68b", [:mix], [{:plug, "~> 1.5", [hex: :plug, 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_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"}, "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_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"}, "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"}, "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": {: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_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_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"}, "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"},
@ -109,7 +112,7 @@
"spandex_ecto": {:hex, :spandex_ecto, "0.4.0", "deaeaddc11a35f1c551206c53d09bb93a0da5808dbef751430e465c8c7de01d3", [:mix], [{:spandex, "~> 2.2", [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"}, "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.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"telemetry": {:hex, :telemetry, "0.3.0", "099a7f3ce31e4780f971b4630a3c22ec66d22208bc090fe33a2a3a6a67754a73", [:rebar3], [], "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"}, "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"}, "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"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},

Loading…
Cancel
Save