Merge branch 'master' into set-url-params-for-prod-explicitly

pull/2337/head
Victor Baranov 5 years ago committed by GitHub
commit cd0c33ab36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .dialyzer-ignore
  2. 7
      CHANGELOG.md
  3. 2
      apps/block_scout_web/assets/js/app.js
  4. 28
      apps/block_scout_web/assets/js/lib/smart_contract/new_smart_contract_form.js
  5. 144
      apps/block_scout_web/assets/js/pages/verification_form.js
  6. 5
      apps/block_scout_web/config/config.exs
  7. 6
      apps/block_scout_web/config/dev.exs
  8. 14
      apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
  9. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_coin_balance_controller.ex
  10. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex
  11. 20
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
  12. 12
      apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
  13. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_decompiled_contract_controller.ex
  14. 6
      apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex
  15. 8
      apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
  16. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
  17. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex
  18. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_token_transfer_controller.ex
  19. 6
      apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
  20. 11
      apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex
  21. 4
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
  22. 36
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  23. 1
      apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
  24. 4
      apps/block_scout_web/lib/block_scout_web/resolvers/transaction.ex
  25. 8
      apps/block_scout_web/lib/block_scout_web/router.ex
  26. 4
      apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex
  27. 26
      apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
  28. 14
      apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex
  29. 2
      apps/block_scout_web/lib/block_scout_web/templates/tokens/overview/_details.html.eex
  30. 6
      apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
  31. 12
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  32. 77
      apps/block_scout_web/priv/gettext/default.pot
  33. 83
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  34. 2
      apps/block_scout_web/test/block_scout_web/views/address_view_test.exs
  35. 4
      apps/block_scout_web/test/support/conn_case.ex
  36. 4
      apps/block_scout_web/test/support/feature_case.ex
  37. 2
      apps/explorer/config/config.exs
  38. 2
      apps/explorer/config/test.exs
  39. 26
      apps/explorer/lib/explorer/application.ex
  40. 95
      apps/explorer/lib/explorer/chain.ex
  41. 5
      apps/explorer/lib/explorer/chain/address.ex
  42. 16
      apps/explorer/lib/explorer/chain/address_token_transfer_csv_exporter.ex
  43. 14
      apps/explorer/lib/explorer/chain/address_transaction_csv_exporter.ex
  44. 2
      apps/explorer/lib/explorer/chain/cache/block_count.ex
  45. 2
      apps/explorer/lib/explorer/chain/cache/block_number.ex
  46. 2
      apps/explorer/lib/explorer/chain/cache/blocks.ex
  47. 2
      apps/explorer/lib/explorer/chain/cache/net_version.ex
  48. 2
      apps/explorer/lib/explorer/chain/cache/transaction_count.ex
  49. 2
      apps/explorer/lib/explorer/chain/cache/transactions.ex
  50. 19
      apps/explorer/lib/explorer/chain/data.ex
  51. 2
      apps/explorer/lib/explorer/chain/events/publisher.ex
  52. 4
      apps/explorer/lib/explorer/chain/events/subscriber.ex
  53. 6
      apps/explorer/lib/explorer/chain/smart_contract.ex
  54. 12
      apps/explorer/lib/explorer/chain/smart_contract/external_library.ex
  55. 5
      apps/explorer/lib/explorer/chain/supply/rsk.ex
  56. 7
      apps/explorer/lib/explorer/graphql.ex
  57. 13
      apps/explorer/lib/explorer/market/history/source/crypto_compare.ex
  58. 7
      apps/explorer/lib/explorer/market/market.ex
  59. 23
      apps/explorer/lib/explorer/smart_contract/publisher.ex
  60. 23
      apps/explorer/lib/explorer/smart_contract/publisher_worker.ex
  61. 1
      apps/explorer/mix.exs
  62. 13
      apps/explorer/priv/repo/migrations/20190709103104_add_external_libraries_to_smart_contracts.exs
  63. 59
      apps/explorer/test/explorer/chain/block_number_cache_test.exs
  64. 24
      apps/explorer/test/explorer/chain/cache/block_count_test.exs
  65. 59
      apps/explorer/test/explorer/chain/cache/block_number_test.exs
  66. 36
      apps/explorer/test/explorer/chain/cache/blocks_test.exs
  67. 54
      apps/explorer/test/explorer/chain/cache/transaction_count_test.exs
  68. 34
      apps/explorer/test/explorer/chain/cache/transactions_test.exs
  69. 54
      apps/explorer/test/explorer/chain/transaction_count_cache_test.exs
  70. 14
      apps/explorer/test/explorer/chain/transaction_test.exs
  71. 125
      apps/explorer/test/explorer/chain_test.exs
  72. 18
      apps/explorer/test/explorer/graphql_test.exs
  73. 54
      apps/explorer/test/explorer/market/history/source/crypto_compare_test.exs
  74. 4
      apps/explorer/test/explorer/market/market_history_cache_test.exs
  75. 27
      apps/explorer/test/explorer/market/market_test.exs
  76. 10
      apps/explorer/test/support/data_case.ex
  77. 10
      apps/indexer/lib/indexer/block/fetcher.ex
  78. 5
      apps/indexer/lib/indexer/fetcher/coin_balance_on_demand.ex
  79. 3
      mix.lock

@ -4,4 +4,6 @@
apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex:400: Function timestamp_to_datetime/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: Function microseconds_time/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: The call 'Elixir.System':convert_time_unit(__@1::any(),'native','microseconds') breaks the contract (integer(),time_unit() | 'native',time_unit() | 'native') -> integer()
apps/block_scout_web/lib/block_scout_web/views/layout_view.ex:174: The call 'Elixir.Poison.Parser':'parse!'(any(),#{'keys':='atoms!'}) will never return since the success typing is (binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []),[{atom(),_}]) -> 'false' | 'nil' | 'true' | binary() | ['false' | 'nil' | 'true' | binary() | [any()] | number() | map()] | number() | map() and the contract is (iodata(),'Elixir.Keyword':t()) -> t()
apps/block_scout_web/lib/block_scout_web/views/layout_view.ex:174: The call 'Elixir.Poison.Parser':'parse!'(any(),#{'keys':='atoms!'}) will never return since the success typing is (binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []),[{atom(),_}]) -> 'false' | 'nil' | 'true' | binary() | ['false' | 'nil' | 'true' | binary() | [any()] | number() | map()] | number() | map() and the contract is (iodata(),'Elixir.Keyword':t()) -> t()
apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The pattern 'false' can never match the type 'true'
apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The test 5 == 'infinity' can never evaluate to 'true'

@ -1,11 +1,12 @@
## Current
### Features
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
### Fixes
- [#2337](https://github.com/poanetwork/blockscout/pull/2337) - set url params for prod explicitly
- [#2341](https://github.com/poanetwork/blockscout/pull/2341) - fix transaction input json encoding
- [#2311](https://github.com/poanetwork/blockscout/pull/2311) - fix market history overriding with zeroes
- [#2310](https://github.com/poanetwork/blockscout/pull/2310) - parse url for api docs
- [#2299](https://github.com/poanetwork/blockscout/pull/2299) - fix interpolation in error message
- [#2303](https://github.com/poanetwork/blockscout/pull/2303) - fix transaction csv download link
@ -13,11 +14,15 @@
- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue
### Chore
- [#2325](https://github.com/poanetwork/blockscout/pull/2325) - Reduce function input to address' hash only where possible
- [#2323](https://github.com/poanetwork/blockscout/pull/2323) - Group Explorer caches
- [#2305](https://github.com/poanetwork/blockscout/pull/2305) - Improve Address controllers
- [#2302](https://github.com/poanetwork/blockscout/pull/2302) - fix names for xDai source
- [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment
- [#2307](https://github.com/poanetwork/blockscout/pull/2307) - add GoJoy to README
- [#2293](https://github.com/poanetwork/blockscout/pull/2293) - remove request idle timeout configuration
## 2.0.1-beta

@ -34,6 +34,7 @@ import './pages/transactions'
import './pages/favorites'
import './pages/network-search'
import './pages/layout'
import './pages/verification_form'
import './pages/admin/tasks.js'
@ -46,7 +47,6 @@ import './lib/market_history_chart'
import './lib/pending_transactions_toggle'
import './lib/pretty_json'
import './lib/reload_button'
import './lib/smart_contract/new_smart_contract_form'
import './lib/smart_contract/read_only_functions'
import './lib/smart_contract/wei_ether_converter'
import './lib/stop_propagation'

@ -1,28 +0,0 @@
import $ from 'jquery'
$(function () {
$('.js-btn-add-contract-libraries').on('click', function () {
$('.js-smart-contract-libraries-wrapper').show()
$(this).hide()
})
$('.js-smart-contract-form-reset').on('click', function () {
$('.js-contract-library-form-group').removeClass('active')
$('.js-contract-library-form-group').first().addClass('active')
$('.js-smart-contract-libraries-wrapper').hide()
$('.js-btn-add-contract-libraries').show()
$('.js-add-contract-library-wrapper').show()
})
$('.js-btn-add-contract-library').on('click', function () {
let nextContractLibrary = $('.js-contract-library-form-group.active').next('.js-contract-library-form-group')
if (nextContractLibrary) {
nextContractLibrary.addClass('active')
}
if ($('.js-contract-library-form-group.active').length === $('.js-contract-library-form-group').length) {
$('.js-add-contract-library-wrapper').hide()
}
})
})

@ -0,0 +1,144 @@
import $ from 'jquery'
import _ from 'lodash'
import URI from 'urijs'
import humps from 'humps'
import { subscribeChannel } from '../socket'
import { createStore, connectElements } from '../lib/redux_helpers.js'
export const initialState = {
channelDisconnected: false,
addressHash: null,
newForm: null
}
export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD':
case 'ELEMENTS_LOAD': {
return Object.assign({}, state, _.omit(action, 'type'))
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
return Object.assign({}, state, {
channelDisconnected: true
})
}
case 'RECEIVED_VERIFICATION_RESULT': {
if (action.msg.verificationResult === 'ok') {
return window.location.replace(window.location.href.split('/contract_verifications')[0] + '/contracts')
} else {
return Object.assign({}, state, {
newForm: action.msg.verificationResult
})
}
}
default:
return state
}
}
const elements = {
'[data-selector="channel-disconnected-message"]': {
render ($el, state) {
if (state.channelDisconnected) $el.show()
}
},
'[data-page="contract-verification"]': {
render ($el, state) {
if (state.newForm) {
$el.replaceWith(state.newForm)
$('button[data-button-loading="animation"]').click(event => {
$('#loading').removeClass('d-none')
})
$(function () {
$('.js-btn-add-contract-libraries').on('click', function () {
$('.js-smart-contract-libraries-wrapper').show()
$(this).hide()
})
$('.js-smart-contract-form-reset').on('click', function () {
$('.js-contract-library-form-group').removeClass('active')
$('.js-contract-library-form-group').first().addClass('active')
$('.js-smart-contract-libraries-wrapper').hide()
$('.js-btn-add-contract-libraries').show()
$('.js-add-contract-library-wrapper').show()
})
$('.js-btn-add-contract-library').on('click', function () {
let nextContractLibrary = $('.js-contract-library-form-group.active').next('.js-contract-library-form-group')
if (nextContractLibrary) {
nextContractLibrary.addClass('active')
}
if ($('.js-contract-library-form-group.active').length === $('.js-contract-library-form-group').length) {
$('.js-add-contract-library-wrapper').hide()
}
})
})
return $el
}
return $el
}
}
}
const $contractVerificationPage = $('[data-page="contract-verification"]')
if ($contractVerificationPage.length) {
const store = createStore(reducer)
const addressHash = $('#smart_contract_address_hash').val()
const { filter, blockNumber } = humps.camelizeKeys(URI(window.location).query(true))
store.dispatch({
type: 'PAGE_LOAD',
addressHash,
filter,
beyondPageOne: !!blockNumber
})
connectElements({ store, elements })
const addressChannel = subscribeChannel(`addresses:${addressHash}`)
addressChannel.onError(() => store.dispatch({
type: 'CHANNEL_DISCONNECTED'
}))
addressChannel.on('verification', (msg) => store.dispatch({
type: 'RECEIVED_VERIFICATION_RESULT',
msg: humps.camelizeKeys(msg)
}))
$('button[data-button-loading="animation"]').click(event => {
$('#loading').removeClass('d-none')
})
$(function () {
$('.js-btn-add-contract-libraries').on('click', function () {
$('.js-smart-contract-libraries-wrapper').show()
$(this).hide()
})
$('.js-smart-contract-form-reset').on('click', function () {
$('.js-contract-library-form-group').removeClass('active')
$('.js-contract-library-form-group').first().addClass('active')
$('.js-smart-contract-libraries-wrapper').hide()
$('.js-btn-add-contract-libraries').show()
$('.js-add-contract-library-wrapper').show()
})
$('.js-btn-add-contract-library').on('click', function () {
let nextContractLibrary = $('.js-contract-library-form-group.active').next('.js-contract-library-form-group')
if (nextContractLibrary) {
nextContractLibrary.addClass('active')
}
if ($('.js-contract-library-form-group.active').length === $('.js-contract-library-form-group').length) {
$('.js-add-contract-library-wrapper').hide()
}
})
})
}

@ -35,11 +35,6 @@ config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: t
# Configures the endpoint
config :block_scout_web, BlockScoutWeb.Endpoint,
instrumenters: [BlockScoutWeb.Prometheus.Instrumenter, SpandexPhoenix.Instrumenter],
http: [
protocol_options: [
idle_timeout: 90_000
]
],
url: [
host: System.get_env("BLOCKSCOUT_HOST") || "localhost",
path: System.get_env("NETWORK_PATH") || "/"

@ -16,9 +16,6 @@ port =
config :block_scout_web, BlockScoutWeb.Endpoint,
http: [
protocol_options: [
idle_timeout: 90_000
],
port: port || 4000
],
url: [
@ -27,9 +24,6 @@ config :block_scout_web, BlockScoutWeb.Endpoint,
path: System.get_env("NETWORK_PATH") || "/"
],
https: [
protocol_options: [
idle_timeout: 90_000
],
port: (port && port + 1) || 4001,
cipher_suite: :strong,
certfile: System.get_env("CERTFILE") || "priv/cert/selfsigned.pem",

@ -11,7 +11,7 @@ defmodule BlockScoutWeb.AddressChannel do
alias Explorer.ExchangeRates.Token
alias Phoenix.View
intercept(["balance_update", "coin_balance", "count", "internal_transaction", "transaction"])
intercept(["balance_update", "coin_balance", "count", "internal_transaction", "transaction", "verification_result"])
def join("addresses:" <> address_hash, _params, socket) do
{:ok, %{}, assign(socket, :address_hash, address_hash)}
@ -58,6 +58,18 @@ defmodule BlockScoutWeb.AddressChannel do
end
end
def handle_out("verification_result", result, socket) do
case result[:result] do
{:ok, _contract} ->
push(socket, "verification", %{verification_result: :ok})
{:noreply, socket}
{:error, result} ->
push(socket, "verification", %{verification_result: result})
{:noreply, socket}
end
end
def handle_out("count", %{count: count}, socket) do
Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale)

@ -64,8 +64,8 @@ defmodule BlockScoutWeb.AddressCoinBalanceController do
address: address,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address),
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash),
current_path: current_path(conn)
)
end

@ -16,8 +16,8 @@ defmodule BlockScoutWeb.AddressContractController do
address: address,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
:error ->

@ -2,7 +2,7 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
use BlockScoutWeb, :controller
alias Explorer.Chain.SmartContract
alias Explorer.SmartContract.{Publisher, Solidity.CodeCompiler, Solidity.CompilerVersion}
alias Explorer.SmartContract.{PublisherWorker, Solidity.CodeCompiler, Solidity.CompilerVersion}
def new(conn, %{"address_id" => address_hash_string}) do
changeset =
@ -16,31 +16,21 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
render(conn, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions()
evm_versions: CodeCompiler.allowed_evm_versions(),
address_hash: address_hash_string
)
end
def create(
conn,
%{
"address_id" => address_hash_string,
"smart_contract" => smart_contract,
"external_libraries" => external_libraries
}
) do
case Publisher.publish(address_hash_string, smart_contract, external_libraries) do
{:ok, _smart_contract} ->
redirect(conn, to: address_contract_path(conn, :index, address_hash_string))
Que.add(PublisherWorker, {smart_contract["address_hash"], smart_contract, external_libraries, conn})
{:error, changeset} ->
{:ok, compiler_versions} = CompilerVersion.fetch_versions()
render(conn, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions()
)
end
send_resp(conn, 204, "")
end
def parse_optimization_runs(%{"runs" => runs}) do

@ -5,7 +5,7 @@ defmodule BlockScoutWeb.AddressController do
alias BlockScoutWeb.AddressView
alias Explorer.{Chain, Market}
alias Explorer.Chain.Address
alias Explorer.Chain.Hash
alias Explorer.ExchangeRates.Token
alias Phoenix.View
@ -45,7 +45,7 @@ defmodule BlockScoutWeb.AddressController do
exchange_rate: exchange_rate,
total_supply: total_supply,
tx_count: tx_count,
validation_count: validation_count(address)
validation_count: validation_count(address.hash)
)
end)
@ -69,11 +69,11 @@ defmodule BlockScoutWeb.AddressController do
redirect(conn, to: address_transaction_path(conn, :index, id))
end
def transaction_count(%Address{} = address) do
Chain.total_transactions_sent_by_address(address)
def transaction_count(%Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash) do
Chain.total_transactions_sent_by_address(address_hash)
end
def validation_count(%Address{} = address) do
Chain.address_to_validation_count(address)
def validation_count(%Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash) do
Chain.address_to_validation_count(address_hash)
end
end

@ -16,8 +16,8 @@ defmodule BlockScoutWeb.AddressDecompiledContractController do
address: address,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
:error ->

@ -28,7 +28,7 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do
|> Keyword.merge(paging_options(params))
|> Keyword.merge(current_filter(params))
internal_transactions_plus_one = Chain.address_to_internal_transactions(address, full_options)
internal_transactions_plus_one = Chain.address_to_internal_transactions(address_hash, full_options)
{internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one)
next_page_path =
@ -71,8 +71,8 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do
current_path: current_path(conn),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
filter: params["filter"],
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
:error ->

@ -17,7 +17,7 @@ defmodule BlockScoutWeb.AddressLogsController do
def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash, [], false) do
logs_plus_one = Chain.address_to_logs(address, paging_options(params))
logs_plus_one = Chain.address_to_logs(address_hash, paging_options(params))
{results, next_page} = split_list_by_page(logs_plus_one)
next_page_url =
@ -63,8 +63,8 @@ defmodule BlockScoutWeb.AddressLogsController do
current_path: current_path(conn),
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
_ ->
@ -79,7 +79,7 @@ defmodule BlockScoutWeb.AddressLogsController do
formatted_topic = if String.starts_with?(topic, "0x"), do: topic, else: "0x" <> topic
logs_plus_one = Chain.address_to_logs(address, topic: formatted_topic)
logs_plus_one = Chain.address_to_logs(address_hash, topic: formatted_topic)
{results, next_page} = split_list_by_page(logs_plus_one)

@ -23,8 +23,8 @@ defmodule BlockScoutWeb.AddressReadContractController do
address: address,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
:error ->

@ -64,8 +64,8 @@ defmodule BlockScoutWeb.AddressTokenController do
current_path: current_path(conn),
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
:error ->

@ -85,8 +85,8 @@ defmodule BlockScoutWeb.AddressTokenTransferController do
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
current_path: current_path(conn),
token: token,
transaction_count: transaction_count(address),
validation_count: validation_count(address)
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash)
)
else
:error ->

@ -38,7 +38,7 @@ defmodule BlockScoutWeb.AddressTransactionController do
|> Keyword.merge(paging_options(params))
|> Keyword.merge(current_filter(params))
results_plus_one = Chain.address_to_transactions_with_rewards(address, options)
results_plus_one = Chain.address_to_transactions_with_rewards(address_hash, options)
{results, next_page} = split_list_by_page(results_plus_one)
next_page_url =
@ -97,8 +97,8 @@ defmodule BlockScoutWeb.AddressTransactionController do
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
filter: params["filter"],
transaction_count: transaction_count(address),
validation_count: validation_count(address),
transaction_count: transaction_count(address_hash),
validation_count: validation_count(address_hash),
current_path: current_path(conn)
)
else

@ -17,7 +17,7 @@ defmodule BlockScoutWeb.AddressValidationController do
def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.find_or_insert_address_from_hash(address_hash, [], false) do
{:ok, _} <- Chain.find_or_insert_address_from_hash(address_hash, [], false) do
full_options =
Keyword.merge(
[
@ -31,7 +31,7 @@ defmodule BlockScoutWeb.AddressValidationController do
paging_options(params)
)
blocks_plus_one = Chain.get_blocks_validated_by_address(full_options, address)
blocks_plus_one = Chain.get_blocks_validated_by_address(full_options, address_hash)
{blocks, next_page} = split_list_by_page(blocks_plus_one)
next_page_path =
@ -63,9 +63,6 @@ defmodule BlockScoutWeb.AddressValidationController do
else
:error ->
unprocessable_entity(conn)
{:error, :not_found} ->
not_found(conn)
end
end
@ -78,8 +75,8 @@ defmodule BlockScoutWeb.AddressValidationController do
address: address,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
current_path: current_path(conn),
transaction_count: transaction_count(address),
validation_count: validation_count(address),
transaction_count: transaction_count(address.hash),
validation_count: validation_count(address.hash),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null()
)
else

@ -3,7 +3,7 @@ defmodule BlockScoutWeb.API.RPC.BlockController do
alias BlockScoutWeb.Chain, as: ChainWeb
alias Explorer.Chain
alias Explorer.Chain.BlockNumberCache
alias Explorer.Chain.Cache.BlockNumber
def getblockreward(conn, params) do
with {:block_param, {:ok, unsafe_block_number}} <- {:block_param, Map.fetch(params, "blockno")},
@ -27,7 +27,7 @@ defmodule BlockScoutWeb.API.RPC.BlockController do
def eth_block_number(conn, params) do
id = Map.get(params, "id", 1)
max_block_number = BlockNumberCache.max_number()
max_block_number = BlockNumber.max_number()
render(conn, :eth_block_number, number: max_block_number, id: id)
end

@ -4,11 +4,13 @@ defmodule BlockScoutWeb.Notifier do
"""
alias Absinthe.Subscription
alias BlockScoutWeb.Endpoint
alias BlockScoutWeb.{AddressContractVerificationView, Endpoint}
alias Explorer.{Chain, Market, Repo}
alias Explorer.Chain.{Address, InternalTransaction, Transaction}
alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token
alias Explorer.SmartContract.{Solidity.CodeCompiler, Solidity.CompilerVersion}
alias Phoenix.View
def handle_event({:chain_event, :addresses, type, addresses}) when type in [:realtime, :on_demand] do
Endpoint.broadcast("addresses:new_address", "count", %{count: Chain.count_addresses_with_balance_from_cache()})
@ -23,6 +25,38 @@ defmodule BlockScoutWeb.Notifier do
Enum.each(address_coin_balances, &broadcast_address_coin_balance/1)
end
def handle_event(
{:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result, conn}}
) do
contract_verification_result =
case contract_verification_result do
{:ok, _} = result ->
result
{:error, changeset} ->
{:ok, compiler_versions} = CompilerVersion.fetch_versions()
result =
View.render_to_string(AddressContractVerificationView, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions(),
address_hash: address_hash,
conn: conn
)
{:error, result}
end
Endpoint.broadcast(
"addresses:#{address_hash}",
"verification_result",
%{
result: contract_verification_result
}
)
end
def handle_event({:chain_event, :block_rewards, :realtime, rewards}) do
if Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:has_emission_funds] do
broadcast_rewards(rewards)

@ -23,6 +23,7 @@ defmodule BlockScoutWeb.RealtimeEventHandler do
Subscriber.to(:transactions, :realtime)
Subscriber.to(:addresses, :on_demand)
Subscriber.to(:address_coin_balances, :on_demand)
Subscriber.to(:contract_verification_result, :on_demand)
# Does not come from the indexer
Subscriber.to(:exchange_rate)
{:ok, []}

@ -12,8 +12,8 @@ defmodule BlockScoutWeb.Resolvers.Transaction do
end
end
def get_by(%Address{} = address, args, _) do
address
def get_by(%Address{hash: address_hash}, args, _) do
address_hash
|> GraphQL.address_to_transactions_query()
|> Connection.from_query(&Repo.all/1, args, options(args))
end

@ -29,6 +29,12 @@ defmodule BlockScoutWeb.Router do
resources("/verified_smart_contracts", VerifiedSmartContractController, only: [:create])
end
scope "/verify_smart_contract" do
pipe_through(:api)
post("/contract_verifications", BlockScoutWeb.AddressContractVerificationController, :create)
end
scope "/api", BlockScoutWeb.API.RPC do
pipe_through(:api)
@ -161,7 +167,7 @@ defmodule BlockScoutWeb.Router do
resources(
"/contract_verifications",
AddressContractVerificationController,
only: [:new, :create],
only: [:new],
as: :verify_contract
)

@ -74,7 +74,7 @@
<%= if contract?(@address) do %>
<%= gettext(">=") %>
<span data-selector="transaction-count">
<%= incoming_transaction_count(@address) %>
<%= incoming_transaction_count(@address.hash) %>
</span>
<%= gettext("Incoming Transactions") %>
<% else %>
@ -146,7 +146,7 @@
</button>
</div>
<div class="modal-body">
<img src="data:image/png;base64, <%= qr_code(@address) %>" class="qr-code" alt="qr_code" title="<%= @address %>" />
<img src="data:image/png;base64, <%= qr_code(@address.hash) %>" class="qr-code" alt="qr_code" title="<%= @address %>" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal"><%= gettext "Close" %></button>

@ -52,17 +52,6 @@
<dd class="col-sm-8 col-md-10"><%= @address.smart_contract.constructor_arguments %></dd>
</dl>
<% end %>
<%= if @address.smart_contract.external_libraries do %>
<section>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "External libraries" %></h3>
</div>
<div class="tile tile-muted mb-4">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= format_smart_contract_abi(@address.smart_contract.abi) %></code>
</pre>
</div>
</section>
<% end %>
</div>
<hr/>
<section>
@ -109,7 +98,7 @@
</div>
<% {:ok, contract_code} -> %>
<div class="d-flex justify-content-between align-items-baseline">
<h2 class="card-title"><%= gettext "Contract Byte Code" %></h2>
<h3><%= gettext "Contract Byte Code" %></h3>
<button type="button" class="btn-line" id="button" data-clipboard-text="<%= contract_code %>" aria-label="copy contract creation code">
<%= gettext "Copy Contract Byte Code" %>
</button>
@ -120,6 +109,19 @@
<% end %>
</section>
<%= if BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %>
<%= if @address.smart_contract.external_libraries && @address.smart_contract.external_libraries != [] do %>
<section>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "External libraries" %></h3>
</div>
<div class="tile tile-muted mb-4">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= format_external_libraries(@address.smart_contract.external_libraries) %></code>
</pre>
</div>
</section>
<% end %>
<% end %>
</div>
</div>
</section>

@ -1,9 +1,15 @@
<section class="container new-smart-contract-container">
<section data-page="contract-verification" class="container new-smart-contract-container">
<div data-selector="channel-disconnected-message" style="display: none;">
<div data-selector="reload-button" class="alert alert-danger">
<a href="#" class="alert-link"><%= gettext "Connection Lost" %></a>
</div>
</div>
<div class="new-smart-contract-form">
<h1 class="smart-contract-title"><%= gettext "New Smart Contract Verification" %></h1>
<%= form_for @changeset,
address_verify_contract_path(@conn, :create, @conn.params["address_id"]),
address_contract_verification_path(@conn, :create),
[],
fn f -> %>
@ -240,13 +246,13 @@
</span>
<%= gettext("Loading....") %>
</button>
<%= submit gettext("Verify & publish"), class: "btn-full-primary mr-2", "data-loading": "animation" %>
<%= submit gettext("Verify & publish"), class: "btn-full-primary mr-2", "data-button-loading": "animation" %>
<%= reset gettext("Reset"), class: "btn-line mr-2 js-smart-contract-form-reset" %>
<%=
link(
gettext("Cancel"),
class: "btn-no-border",
to: address_contract_path(@conn, :index, @conn.params["address_id"])
to: address_contract_path(@conn, :index, @address_hash)
)
%>
</div>

@ -109,7 +109,7 @@
</button>
</div>
<div class="modal-body">
<img src="data:image/png;base64, <%= BlockScoutWeb.AddressView.qr_code(@token.contract_address) %> " class="qr-code" alt="qr_code" title="<%= @token.contract_address %>" />
<img src="data:image/png;base64, <%= BlockScoutWeb.AddressView.qr_code(@token.contract_address_hash) %> " class="qr-code" alt="qr_code" title="<%= @token.contract_address %>" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal"><%= gettext "Close" %></button>

@ -21,6 +21,12 @@ defmodule BlockScoutWeb.AddressContractView do
def format_optimization_text(true), do: gettext("true")
def format_optimization_text(false), do: gettext("false")
def format_external_libraries(libraries) do
Enum.reduce(libraries, "", fn %{name: name, address_hash: address_hash}, acc ->
acc <> name <> " : " <> address_hash <> "\n"
end)
end
def contract_lines_with_index(contract_source_code) do
contract_lines = String.split(contract_source_code, "\n")

@ -189,8 +189,8 @@ defmodule BlockScoutWeb.AddressView do
|> Timex.format!("{M}-{D}-{YYYY}")
end
def qr_code(%Address{hash: hash}) do
hash
def qr_code(address_hash) do
address_hash
|> to_string()
|> QRCode.to_png()
|> Base.encode64()
@ -219,10 +219,10 @@ defmodule BlockScoutWeb.AddressView do
def token_title(%Token{name: name, symbol: symbol}), do: "#{name} (#{symbol})"
def incoming_transaction_count(%Address{} = address) do
count = Chain.address_to_incoming_transaction_count(address)
Cldr.Number.to_string!(count, format: "#,###")
def incoming_transaction_count(address_hash) do
address_hash
|> Chain.address_to_incoming_transaction_count()
|> Cldr.Number.to_string!(format: "#,###")
end
def trimmed_hash(%Hash{} = hash) do

@ -197,7 +197,7 @@ msgid "Blocks Validated"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:253
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47
msgid "Cancel"
msgstr ""
@ -225,7 +225,7 @@ msgid "Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:34
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "Compiler"
msgstr ""
@ -258,12 +258,12 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:82
#: lib/block_scout_web/templates/address_contract/index.html.eex:71
msgid "Contract ABI"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:12
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18
#: lib/block_scout_web/views/address_view.ex:97
msgid "Contract Address"
msgstr ""
@ -286,7 +286,7 @@ msgid "Contract Creation"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:23
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:29
msgid "Contract Name"
msgstr ""
@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:70
#: lib/block_scout_web/templates/address_contract/index.html.eex:59
msgid "Contract source code"
msgstr ""
@ -560,7 +560,7 @@ msgid "Name"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:61
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:67
msgid "No"
msgstr ""
@ -651,7 +651,7 @@ msgid "Request URL"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:244
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:250
msgid "Reset"
msgstr ""
@ -939,7 +939,7 @@ msgid "Verify & Publish"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:243
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:249
msgid "Verify & publish"
msgstr ""
@ -989,7 +989,7 @@ msgid "Wei"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:66
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:72
msgid "Yes"
msgstr ""
@ -1062,7 +1062,7 @@ msgid "Loading..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:241
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
msgid "Loading...."
msgstr ""
@ -1405,17 +1405,17 @@ msgid "Support"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:84
#: lib/block_scout_web/templates/address_contract/index.html.eex:73
msgid "Copy ABI"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:100
#: lib/block_scout_web/templates/address_contract/index.html.eex:89
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:72
#: lib/block_scout_web/templates/address_contract/index.html.eex:61
msgid "Copy Source Code"
msgstr ""
@ -1425,7 +1425,7 @@ msgid "Genesis Block"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:112
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:118
msgid "Contract Libraries"
msgstr ""
@ -1488,7 +1488,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:35
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:45
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:51
msgid "EVM Version"
msgstr ""
@ -1519,7 +1519,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:45
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:77
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:83
msgid "Optimization runs"
msgstr ""
@ -1585,27 +1585,27 @@ msgid "Block Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:112
#: lib/block_scout_web/templates/address_contract/index.html.eex:101
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:98
#: lib/block_scout_web/templates/address_contract/index.html.eex:87
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:104
#: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:114
#: lib/block_scout_web/templates/address_contract/index.html.eex:103
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:105
#: lib/block_scout_web/templates/address_contract/index.html.eex:94
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
@ -1655,35 +1655,35 @@ msgid "Topic"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:98
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:104
msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:87
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:93
msgid "Enter the Solidity Contract Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:127
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:149
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:171
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:193
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:215
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:133
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:155
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:177
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:199
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:221
msgid "Library Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:117
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:183
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:205
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:123
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:145
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:167
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:189
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:211
msgid "Library Name"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:3
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:9
msgid "New Smart Contract Verification"
msgstr ""
@ -1769,7 +1769,7 @@ msgid "ERC-721 "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:58
#: lib/block_scout_web/templates/address_contract/index.html.eex:116
msgid "External libraries"
msgstr ""
@ -1797,3 +1797,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:12
msgid "Use the search box to find a hosted network, or select from the list of available networks below."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost"
msgstr ""

@ -197,7 +197,7 @@ msgid "Blocks Validated"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:253
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47
msgid "Cancel"
msgstr ""
@ -225,7 +225,7 @@ msgid "Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:34
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "Compiler"
msgstr ""
@ -258,12 +258,12 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:82
#: lib/block_scout_web/templates/address_contract/index.html.eex:71
msgid "Contract ABI"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:12
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18
#: lib/block_scout_web/views/address_view.ex:97
msgid "Contract Address"
msgstr ""
@ -286,7 +286,7 @@ msgid "Contract Creation"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:23
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:29
msgid "Contract Name"
msgstr ""
@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:70
#: lib/block_scout_web/templates/address_contract/index.html.eex:59
msgid "Contract source code"
msgstr ""
@ -560,7 +560,7 @@ msgid "Name"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:61
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:67
msgid "No"
msgstr ""
@ -651,7 +651,7 @@ msgid "Request URL"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:244
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:250
msgid "Reset"
msgstr ""
@ -674,7 +674,7 @@ msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/address_token_balance/_token_balances.html.eex:28
#: lib/block_scout_web/templates/address_token_balance/_token_balances.html.eex:30
msgid "Search tokens"
msgstr ""
@ -877,7 +877,7 @@ msgid "Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tile.html.eex:19
#: lib/block_scout_web/templates/address/_tile.html.eex:31
msgid "Transactions sent"
msgstr ""
@ -923,7 +923,7 @@ msgid "Validated Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tile.html.eex:23
#: lib/block_scout_web/templates/address/_tile.html.eex:35
msgid "Validations"
msgstr ""
@ -939,7 +939,7 @@ msgid "Verify & Publish"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:243
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:249
msgid "Verify & publish"
msgstr ""
@ -989,7 +989,7 @@ msgid "Wei"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:66
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:72
msgid "Yes"
msgstr ""
@ -1062,7 +1062,7 @@ msgid "Loading..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:241
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
msgid "Loading...."
msgstr ""
@ -1405,17 +1405,17 @@ msgid "Support"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:84
#: lib/block_scout_web/templates/address_contract/index.html.eex:73
msgid "Copy ABI"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:100
#: lib/block_scout_web/templates/address_contract/index.html.eex:89
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:72
#: lib/block_scout_web/templates/address_contract/index.html.eex:61
msgid "Copy Source Code"
msgstr ""
@ -1425,7 +1425,7 @@ msgid "Genesis Block"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:112
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:118
msgid "Contract Libraries"
msgstr ""
@ -1488,7 +1488,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:35
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:45
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:51
msgid "EVM Version"
msgstr ""
@ -1519,7 +1519,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:45
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:77
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:83
msgid "Optimization runs"
msgstr ""
@ -1585,27 +1585,27 @@ msgid "Block Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:112
#: lib/block_scout_web/templates/address_contract/index.html.eex:101
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:98
#: lib/block_scout_web/templates/address_contract/index.html.eex:87
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:104
#: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:114
#: lib/block_scout_web/templates/address_contract/index.html.eex:103
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:105
#: lib/block_scout_web/templates/address_contract/index.html.eex:94
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
@ -1655,35 +1655,35 @@ msgid "Topic"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:98
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:104
msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:87
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:93
msgid "Enter the Solidity Contract Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:127
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:149
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:171
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:193
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:215
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:133
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:155
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:177
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:199
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:221
msgid "Library Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:117
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:183
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:205
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:123
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:145
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:167
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:189
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:211
msgid "Library Name"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:3
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:9
msgid "New Smart Contract Verification"
msgstr ""
@ -1769,7 +1769,7 @@ msgid "ERC-721 "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:58
#: lib/block_scout_web/templates/address_contract/index.html.eex:116
msgid "External libraries"
msgstr ""
@ -1797,3 +1797,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:12
msgid "Use the search box to find a hosted network, or select from the list of available networks below."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost"
msgstr ""

@ -199,7 +199,7 @@ defmodule BlockScoutWeb.AddressViewTest do
describe "qr_code/1" do
test "it returns an encoded value" do
address = build(:address)
assert {:ok, _} = Base.decode64(AddressView.qr_code(address))
assert {:ok, _} = Base.decode64(AddressView.qr_code(address.hash))
end
end

@ -38,8 +38,8 @@ defmodule BlockScoutWeb.ConnCase do
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()})
end
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()})
{:ok, conn: Phoenix.ConnTest.build_conn()}
end

@ -27,8 +27,8 @@ defmodule BlockScoutWeb.FeatureCase do
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()})
end
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()})
metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(Explorer.Repo, self())
{:ok, session} = Wallaby.start_session(metadata: metadata)

@ -19,7 +19,7 @@ config :explorer,
config :explorer, Explorer.Counters.AverageBlockTime, enabled: true
config :explorer, Explorer.Chain.BlockNumberCache, enabled: true
config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true
config :explorer, Explorer.ExchangeRates.Source.CoinMarketCap,
pages: String.to_integer(System.get_env("COINMARKETCAP_PAGES") || "10")

@ -13,7 +13,7 @@ config :explorer, Explorer.Repo,
config :explorer, Explorer.ExchangeRates, enabled: false, store: :ets
config :explorer, Explorer.Chain.BlockNumberCache, enabled: false
config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: false
config :explorer, Explorer.KnownTokens, enabled: false, store: :ets

@ -7,13 +7,13 @@ defmodule Explorer.Application do
alias Explorer.Admin
alias Explorer.Chain.{
BlockCountCache,
BlockNumberCache,
BlocksCache,
NetVersionCache,
TransactionCountCache,
TransactionsCache
alias Explorer.Chain.Cache.{
BlockCount,
BlockNumber,
Blocks,
NetVersion,
TransactionCount,
Transactions
}
alias Explorer.Chain.Supply.RSK
@ -41,13 +41,13 @@ defmodule Explorer.Application do
Explorer.SmartContract.SolcDownloader,
{Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents},
{Admin.Recovery, [[], [name: Admin.Recovery]]},
{TransactionCountCache, [[], []]},
{BlockCountCache, []},
con_cache_child_spec(BlocksCache.cache_name()),
con_cache_child_spec(NetVersionCache.cache_name()),
{TransactionCount, [[], []]},
{BlockCount, []},
con_cache_child_spec(Blocks.cache_name()),
con_cache_child_spec(NetVersion.cache_name()),
con_cache_child_spec(MarketHistoryCache.cache_name()),
con_cache_child_spec(RSK.cache_name(), ttl_check_interval: :timer.minutes(1), global_ttl: :timer.minutes(30)),
con_cache_child_spec(TransactionsCache.cache_name())
con_cache_child_spec(Transactions.cache_name())
]
children = base_children ++ configurable_children()
@ -56,7 +56,7 @@ defmodule Explorer.Application do
res = Supervisor.start_link(children, opts)
BlockNumberCache.setup()
BlockNumber.setup()
res
end

@ -31,9 +31,6 @@ defmodule Explorer.Chain do
Address.CurrentTokenBalance,
Address.TokenBalance,
Block,
BlockCountCache,
BlockNumberCache,
BlocksCache,
Data,
DecompiledSmartContract,
Hash,
@ -45,12 +42,19 @@ defmodule Explorer.Chain do
Token,
TokenTransfer,
Transaction,
TransactionCountCache,
TransactionsCache,
Wei
}
alias Explorer.Chain.Block.{EmissionReward, Reward}
alias Explorer.Chain.Cache.{
BlockCount,
BlockNumber,
Blocks,
TransactionCount,
Transactions
}
alias Explorer.Chain.Import.Runner
alias Explorer.Counters.AddressesWithBalanceCounter
alias Explorer.Market.MarketHistoryCache
@ -126,7 +130,7 @@ defmodule Explorer.Chain do
end
@doc """
`t:Explorer.Chain.InternalTransaction/0`s from `address`.
`t:Explorer.Chain.InternalTransaction/0`s from the address with the given `hash`.
This function excludes any internal transactions in the results where the
internal transaction has no siblings within the parent transaction.
@ -145,10 +149,10 @@ defmodule Explorer.Chain do
transactions older than the `block_number`, `transaction index`, and `index` that are passed.
"""
@spec address_to_internal_transactions(Address.t(), [paging_options | necessity_by_association_option]) :: [
@spec address_to_internal_transactions(Hash.Address.t(), [paging_options | necessity_by_association_option]) :: [
InternalTransaction.t()
]
def address_to_internal_transactions(%Address{hash: hash}, options \\ []) do
def address_to_internal_transactions(hash, options \\ []) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
direction = Keyword.get(options, :direction)
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@ -171,13 +175,13 @@ defmodule Explorer.Chain do
end
@doc """
Get the total number of transactions sent by the given address according to the last block indexed.
Get the total number of transactions sent by the address with the given hash according to the last block indexed.
We have to increment +1 in the last nonce result because it works like an array position, the first
nonce has the value 0. When last nonce is nil, it considers that the given address has 0 transactions.
"""
@spec total_transactions_sent_by_address(Address.t()) :: non_neg_integer()
def total_transactions_sent_by_address(%Address{hash: address_hash}) do
@spec total_transactions_sent_by_address(Hash.Address.t()) :: non_neg_integer()
def total_transactions_sent_by_address(address_hash) do
last_nonce =
address_hash
|> Transaction.last_nonce_by_address_query()
@ -190,9 +194,9 @@ defmodule Explorer.Chain do
end
@doc """
Fetches the transactions related to the given address, including transactions
that only have the address in the `token_transfers` related table and rewards
for block validation.
Fetches the transactions related to the address with the given hash, including
transactions that only have the address in the `token_transfers` related table
and rewards for block validation.
This query is divided into multiple subqueries intentionally in order to
improve the listing performance.
@ -214,14 +218,10 @@ defmodule Explorer.Chain do
the `block_number` and `index` that are passed.
"""
@spec address_to_transactions_with_rewards(Address.t(), [paging_options | necessity_by_association_option]) :: [
@spec address_to_transactions_with_rewards(Hash.Address.t(), [paging_options | necessity_by_association_option]) :: [
Transaction.t()
]
def address_to_transactions_with_rewards(
%Address{hash: %Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash},
options \\ []
)
when is_list(options) do
def address_to_transactions_with_rewards(address_hash, options \\ []) when is_list(options) do
direction = Keyword.get(options, :direction)
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
@ -256,17 +256,11 @@ defmodule Explorer.Chain do
end
end
@spec address_to_logs(Address.t(), Keyword.t()) :: [
Log.t()
]
def address_to_logs(
%Address{hash: %Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash},
options \\ []
)
when is_list(options) do
@spec address_to_logs(Hash.Address.t(), Keyword.t()) :: [Log.t()]
def address_to_logs(address_hash, options \\ []) when is_list(options) do
paging_options = Keyword.get(options, :paging_options) || %PagingOptions{page_size: 50}
{block_number, transaction_index, log_index} = paging_options.key || {BlockNumberCache.max_number(), 0, 0}
{block_number, transaction_index, log_index} = paging_options.key || {BlockNumber.max_number(), 0, 0}
base_query =
from(log in Log,
@ -442,8 +436,8 @@ defmodule Explorer.Chain do
Repo.aggregate(query, :count, :hash)
end
@spec address_to_incoming_transaction_count(Address.t()) :: non_neg_integer()
def address_to_incoming_transaction_count(%Address{hash: address_hash}) do
@spec address_to_incoming_transaction_count(Hash.Address.t()) :: non_neg_integer()
def address_to_incoming_transaction_count(address_hash) do
paging_options = %PagingOptions{page_size: @max_incoming_transactions_count}
base_query =
@ -1164,7 +1158,7 @@ defmodule Explorer.Chain do
"""
@spec indexed_ratio() :: Decimal.t()
def indexed_ratio do
{min, max} = BlockNumberCache.min_and_max_numbers()
{min, max} = BlockNumber.min_and_max_numbers()
case {min, max} do
{0, 0} ->
@ -1246,12 +1240,12 @@ defmodule Explorer.Chain do
block_type = Keyword.get(options, :block_type, "Block")
if block_type == "Block" && !paging_options.key do
if BlocksCache.enough_elements?(paging_options.page_size) do
BlocksCache.blocks(paging_options.page_size)
if Blocks.enough_elements?(paging_options.page_size) do
Blocks.blocks(paging_options.page_size)
else
elements = fetch_blocks(block_type, paging_options, necessity_by_association)
BlocksCache.rewrite_cache(elements)
Blocks.rewrite_cache(elements)
elements
end
@ -1333,7 +1327,7 @@ defmodule Explorer.Chain do
end
@doc """
Finds all Blocks validated by the address given.
Finds all Blocks validated by the address with the given hash.
## Options
* `:necessity_by_association` - use to load `t:association/0` as `:required` or `:optional`. If an association is
@ -1347,15 +1341,15 @@ defmodule Explorer.Chain do
"""
@spec get_blocks_validated_by_address(
[paging_options | necessity_by_association_option],
Address.t()
Hash.Address.t()
) :: [Block.t()]
def get_blocks_validated_by_address(options \\ [], %Address{hash: hash}) when is_list(options) do
def get_blocks_validated_by_address(options \\ [], address_hash) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
Block
|> join_associations(necessity_by_association)
|> where(miner_hash: ^hash)
|> where(miner_hash: ^address_hash)
|> page_blocks(paging_options)
|> limit(^paging_options.page_size)
|> order_by(desc: :number)
@ -1379,10 +1373,10 @@ defmodule Explorer.Chain do
end
@doc """
Counts the number of `t:Explorer.Chain.Block.t/0` validated by the `address`.
Counts the number of `t:Explorer.Chain.Block.t/0` validated by the address with the given `hash`.
"""
@spec address_to_validation_count(Address.t()) :: non_neg_integer()
def address_to_validation_count(%Address{hash: hash}) do
@spec address_to_validation_count(Hash.Address.t()) :: non_neg_integer()
def address_to_validation_count(hash) do
query = from(block in Block, where: block.miner_hash == ^hash, select: fragment("COUNT(*)"))
Repo.one(query)
@ -2010,11 +2004,11 @@ defmodule Explorer.Chain do
if is_nil(paging_options.key) do
paging_options.page_size
|> TransactionsCache.take_enough()
|> Transactions.take_enough()
|> case do
nil ->
transactions = fetch_recent_collated_transactions(paging_options, necessity_by_association)
TransactionsCache.update(transactions)
Transactions.update(transactions)
transactions
transactions ->
@ -2159,7 +2153,7 @@ defmodule Explorer.Chain do
"""
@spec transaction_estimated_count() :: non_neg_integer()
def transaction_estimated_count do
cached_value = TransactionCountCache.value()
cached_value = TransactionCount.value()
if is_nil(cached_value) do
%Postgrex.Result{rows: [[rows]]} =
@ -2178,7 +2172,7 @@ defmodule Explorer.Chain do
"""
@spec block_estimated_count() :: non_neg_integer()
def block_estimated_count do
cached_value = BlockCountCache.count()
cached_value = BlockCount.count()
if is_nil(cached_value) do
%Postgrex.Result{rows: [[count]]} = Repo.query!("SELECT reltuples FROM pg_class WHERE relname = 'blocks';")
@ -2426,8 +2420,13 @@ defmodule Explorer.Chain do
naming the address for reference.
"""
@spec create_smart_contract(map()) :: {:ok, SmartContract.t()} | {:error, Ecto.Changeset.t()}
def create_smart_contract(attrs \\ %{}) do
smart_contract_changeset = SmartContract.changeset(%SmartContract{}, attrs)
def create_smart_contract(attrs \\ %{}, external_libraries \\ []) do
new_contract = %SmartContract{}
smart_contract_changeset =
new_contract
|> SmartContract.changeset(attrs)
|> Changeset.put_change(:external_libraries, external_libraries)
insert_result =
Multi.new()

@ -16,13 +16,14 @@ defmodule Explorer.Chain.Address do
DecompiledSmartContract,
Hash,
InternalTransaction,
NetVersionCache,
SmartContract,
Token,
Transaction,
Wei
}
alias Explorer.Chain.Cache.NetVersion
@optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified)a
@required_attrs ~w(hash)a
@allowed_attrs @optional_attrs ++ @required_attrs
@ -169,7 +170,7 @@ defmodule Explorer.Chain.Address do
end
def rsk_checksum(hash) do
chain_id = NetVersionCache.version()
chain_id = NetVersion.version()
string_hash =
hash

@ -4,7 +4,7 @@ defmodule Explorer.Chain.AddressTokenTransferCsvExporter do
"""
alias Explorer.{Chain, PagingOptions}
alias Explorer.Chain.{Address, TokenTransfer, Transaction}
alias Explorer.Chain.{TokenTransfer, Transaction}
alias NimbleCSV.RFC4180
@necessity_by_association [
@ -24,18 +24,18 @@ defmodule Explorer.Chain.AddressTokenTransferCsvExporter do
@paging_options %PagingOptions{page_size: @page_size + 1}
def export(address) do
address
address.hash
|> fetch_all_transactions(@paging_options)
|> to_token_transfers()
|> to_csv_format(address)
|> dump_to_stream()
end
defp fetch_all_transactions(address, paging_options, acc \\ []) do
defp fetch_all_transactions(address_hash, paging_options, acc \\ []) do
options = Keyword.merge(@necessity_by_association, paging_options: paging_options)
transactions =
address
address_hash
|> Chain.address_to_transactions_with_rewards(options)
|> Enum.filter(fn transaction -> Enum.count(transaction.token_transfers) > 0 end)
@ -44,7 +44,7 @@ defmodule Explorer.Chain.AddressTokenTransferCsvExporter do
case Enum.split(transactions, @page_size) do
{_transactions, [%Transaction{block_number: block_number, index: index}]} ->
new_paging_options = %{@paging_options | key: {block_number, index}}
fetch_all_transactions(address, new_paging_options, new_acc)
fetch_all_transactions(address_hash, new_paging_options, new_acc)
{_, []} ->
new_acc
@ -90,7 +90,7 @@ defmodule Explorer.Chain.AddressTokenTransferCsvExporter do
token_transfer.from_address |> to_string() |> String.downcase(),
token_transfer.to_address |> to_string() |> String.downcase(),
token_transfer.token_contract_address |> to_string() |> String.downcase(),
type(token_transfer, address),
type(token_transfer, address.hash),
token_transfer.token.symbol,
token_transfer.amount,
fee(token_transfer.transaction),
@ -102,9 +102,9 @@ defmodule Explorer.Chain.AddressTokenTransferCsvExporter do
Stream.concat([row_names], token_transfer_lists)
end
defp type(%TokenTransfer{from_address_hash: from_address}, %Address{hash: from_address}), do: "OUT"
defp type(%TokenTransfer{from_address_hash: address_hash}, address_hash), do: "OUT"
defp type(%TokenTransfer{to_address_hash: to_address}, %Address{hash: to_address}), do: "IN"
defp type(%TokenTransfer{to_address_hash: address_hash}, address_hash), do: "IN"
defp type(_, _), do: ""

@ -35,23 +35,23 @@ defmodule Explorer.Chain.AddressTransactionCsvExporter do
def export(address) do
exchange_rate = Market.get_exchange_rate(Explorer.coin()) || Token.null()
address
address.hash
|> fetch_all_transactions(@paging_options)
|> to_csv_format(address, exchange_rate)
|> dump_to_stream()
end
defp fetch_all_transactions(address, paging_options, acc \\ []) do
defp fetch_all_transactions(address_hash, paging_options, acc \\ []) do
options = Keyword.merge(@necessity_by_association, paging_options: paging_options)
transactions = Chain.address_to_transactions_with_rewards(address, options)
transactions = Chain.address_to_transactions_with_rewards(address_hash, options)
new_acc = transactions ++ acc
case Enum.split(transactions, @page_size) do
{_transactions, [%Transaction{block_number: block_number, index: index}]} ->
new_paging_options = %{@paging_options | key: {block_number, index}}
fetch_all_transactions(address, new_paging_options, new_acc)
fetch_all_transactions(address_hash, new_paging_options, new_acc)
{_, []} ->
new_acc
@ -93,7 +93,7 @@ defmodule Explorer.Chain.AddressTransactionCsvExporter do
to_string(transaction.from_address),
to_string(transaction.to_address),
to_string(transaction.created_contract_address),
type(transaction, address),
type(transaction, address.hash),
Wei.to(transaction.value, :wei),
fee(transaction),
transaction.status,
@ -107,9 +107,9 @@ defmodule Explorer.Chain.AddressTransactionCsvExporter do
Stream.concat([row_names], transaction_lists)
end
defp type(%Transaction{from_address_hash: from_address}, %Address{hash: from_address}), do: "OUT"
defp type(%Transaction{from_address_hash: address_hash}, address_hash), do: "OUT"
defp type(%Transaction{to_address_hash: to_address}, %Address{hash: to_address}), do: "IN"
defp type(%Transaction{to_address_hash: address_hash}, address_hash), do: "IN"
defp type(_, _), do: ""

@ -1,4 +1,4 @@
defmodule Explorer.Chain.BlockCountCache do
defmodule Explorer.Chain.Cache.BlockCount do
@moduledoc """
Cache for block count.
"""

@ -1,4 +1,4 @@
defmodule Explorer.Chain.BlockNumberCache do
defmodule Explorer.Chain.Cache.BlockNumber do
@moduledoc """
Cache for max and min block numbers.
"""

@ -1,4 +1,4 @@
defmodule Explorer.Chain.BlocksCache do
defmodule Explorer.Chain.Cache.Blocks do
@moduledoc """
Caches the last imported blocks
"""

@ -1,4 +1,4 @@
defmodule Explorer.Chain.NetVersionCache do
defmodule Explorer.Chain.Cache.NetVersion do
@moduledoc """
Caches chain version.
"""

@ -1,4 +1,4 @@
defmodule Explorer.Chain.TransactionCountCache do
defmodule Explorer.Chain.Cache.TransactionCount do
@moduledoc """
Cache for estimated transaction count.
"""

@ -1,4 +1,4 @@
defmodule Explorer.Chain.TransactionsCache do
defmodule Explorer.Chain.Cache.Transactions do
@moduledoc """
Caches the latest imported transactions
"""

@ -7,6 +7,7 @@ defmodule Explorer.Chain.Data do
"""
alias Explorer.Chain.Data
alias Poison.Encoder.BitString
@behaviour Ecto.Type
@ -380,4 +381,22 @@ defmodule Explorer.Chain.Data do
@for.to_string(data)
end
end
defimpl Poison.Encoder do
def encode(data, options) do
data
|> to_string()
|> BitString.encode(options)
end
end
defimpl Jason.Encoder do
alias Jason.Encode
def encode(data, opts) do
data
|> to_string()
|> Encode.string(opts)
end
end
end

@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Publisher do
Publishes events related to the Chain context.
"""
@allowed_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions)a
@allowed_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a
def broadcast(_data, false), do: :ok

@ -3,9 +3,9 @@ defmodule Explorer.Chain.Events.Subscriber do
Subscribes to events related to the Chain context.
"""
@allowed_broadcast_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions)a
@allowed_broadcast_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a
@allowed_broadcast_types ~w(catchup realtime on_demand)a
@allowed_broadcast_types ~w(catchup realtime on_demand contract_verification_result)a
@allowed_events ~w(exchange_rate)a

@ -13,6 +13,7 @@ defmodule Explorer.Chain.SmartContract do
use Explorer.Schema
alias Explorer.Chain.{Address, ContractMethod, DecompiledSmartContract, Hash}
alias Explorer.Chain.SmartContract.ExternalLibrary
alias Explorer.Repo
@typedoc """
@ -212,7 +213,7 @@ defmodule Explorer.Chain.SmartContract do
field(:constructor_arguments, :string)
field(:evm_version, :string)
field(:optimization_runs, :integer)
field(:external_libraries, :map)
embeds_many(:external_libraries, ExternalLibrary)
field(:abi, {:array, :map})
has_many(
@ -247,8 +248,7 @@ defmodule Explorer.Chain.SmartContract do
:abi,
:constructor_arguments,
:evm_version,
:optimization_runs,
:external_libraries
:optimization_runs
])
|> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash])
|> unique_constraint(:address_hash)

@ -0,0 +1,12 @@
defmodule Explorer.Chain.SmartContract.ExternalLibrary do
@moduledoc """
The representation of an external library that was used for a smart contract.
"""
use Ecto.Schema
embedded_schema do
field(:name)
field(:address_hash)
end
end

@ -10,7 +10,8 @@ defmodule Explorer.Chain.Supply.RSK do
alias EthereumJSONRPC.FetchedBalances
alias Explorer.Chain.Address.CoinBalance
alias Explorer.Chain.{Block, BlockNumberCache, Wei}
alias Explorer.Chain.{Block, Wei}
alias Explorer.Chain.Cache.BlockNumber
alias Explorer.Repo
@cache_name :rsk_balance
@ -99,7 +100,7 @@ defmodule Explorer.Chain.Supply.RSK do
def cache_name, do: @cache_name
defp fetch_circulating_value do
max_number = BlockNumberCache.max_number()
max_number = BlockNumber.max_number()
params = [
%{block_quantity: integer_to_quantity(max_number), hash_data: "0x0000000000000000000000000000000001000006"}

@ -12,7 +12,6 @@ defmodule Explorer.GraphQL do
]
alias Explorer.Chain.{
Address,
Hash,
InternalTransaction,
TokenTransfer,
@ -23,12 +22,12 @@ defmodule Explorer.GraphQL do
@doc """
Returns a query to fetch transactions with a matching `to_address_hash`,
`from_address_hash`, or `created_contract_address_hash` field for a given address.
`from_address_hash`, or `created_contract_address_hash` field for a given address hash.
Orders transactions by descending block number and index.
"""
@spec address_to_transactions_query(Address.t()) :: Ecto.Query.t()
def address_to_transactions_query(%Address{hash: %Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash}) do
@spec address_to_transactions_query(Hash.Address.t()) :: Ecto.Query.t()
def address_to_transactions_query(address_hash) do
Transaction
|> order_by([transaction], desc: transaction.block_number, desc: transaction.index)
|> where([transaction], transaction.to_address_hash == ^address_hash)

@ -24,7 +24,12 @@ defmodule Explorer.Market.History.Source.CryptoCompare do
case HTTPoison.get(url, headers) do
{:ok, %Response{body: body, status_code: 200}} ->
{:ok, format_data(body)}
result =
body
|> format_data()
|> reject_zeros()
{:ok, result}
_ ->
:error
@ -67,4 +72,10 @@ defmodule Explorer.Market.History.Source.CryptoCompare do
"#{base_url()}/data/histoday?#{URI.encode_query(query_params)}"
end
defp reject_zeros(items) do
Enum.reject(items, fn item ->
Decimal.equal?(item.closing_price, 0) && Decimal.equal?(item.opening_price, 0)
end)
end
end

@ -40,7 +40,12 @@ defmodule Explorer.Market do
@doc false
def bulk_insert_history(records) do
Repo.insert_all(MarketHistory, records, on_conflict: :replace_all, conflict_target: [:date])
records_without_zeroes =
Enum.reject(records, fn item ->
Decimal.equal?(item.closing_price, 0) && Decimal.equal?(item.opening_price, 0)
end)
Repo.insert_all(MarketHistory, records_without_zeroes, on_conflict: :replace_all, conflict_target: [:date])
end
def add_price(%{symbol: symbol} = token) do

@ -28,17 +28,17 @@ defmodule Explorer.SmartContract.Publisher do
case Verifier.evaluate_authenticity(address_hash, params_with_external_libaries) do
{:ok, %{abi: abi}} ->
publish_smart_contract(address_hash, params, abi)
publish_smart_contract(address_hash, params_with_external_libaries, abi)
{:error, error} ->
{:error, unverified_smart_contract(address_hash, params, error)}
{:error, unverified_smart_contract(address_hash, params_with_external_libaries, error)}
end
end
defp publish_smart_contract(address_hash, params, abi) do
address_hash
|> attributes(params, abi)
|> Chain.create_smart_contract()
attrs = address_hash |> attributes(params, abi)
Chain.create_smart_contract(attrs, attrs.external_libraries)
end
defp unverified_smart_contract(address_hash, params, error) do
@ -64,6 +64,8 @@ defmodule Explorer.SmartContract.Publisher do
nil
end
prepared_external_libraries = prepare_external_libraies(params["external_libraries"])
%{
address_hash: address_hash,
name: params["name"],
@ -73,11 +75,20 @@ defmodule Explorer.SmartContract.Publisher do
optimization: params["optimization"],
contract_source_code: params["contract_source_code"],
constructor_arguments: clean_constructor_arguments,
external_libaries: params["external_libraries"],
external_libraries: prepared_external_libraries,
abi: abi
}
end
defp prepare_external_libraies(nil), do: []
defp prepare_external_libraies(map) do
map
|> Enum.map(fn {key, value} ->
%{name: key, address_hash: value}
end)
end
defp add_external_libraries(params, external_libraries) do
clean_external_libraries =
Enum.reduce(1..5, %{}, fn number, acc ->

@ -0,0 +1,23 @@
defmodule Explorer.SmartContract.PublisherWorker do
@moduledoc """
Background smart contract verification worker.
"""
use Que.Worker, concurrency: 5
alias Explorer.Chain.Events.Publisher, as: EventsPublisher
alias Explorer.SmartContract.Publisher
def perform({address_hash, params, external_libraries, conn}) do
result =
case Publisher.publish(address_hash, params, external_libraries) do
{:ok, _contract} = result ->
result
{:error, changeset} ->
{:error, changeset}
end
EventsPublisher.broadcast([{:contract_verification_result, {address_hash, result, conn}}], :on_demand)
end
end

@ -106,6 +106,7 @@ defmodule Explorer.Mixfile do
},
# bypass optional dependency
{:plug_cowboy, "~> 2.0", only: [:dev, :test]},
{:que, "~> 0.10.1"},
{:sobelow, ">= 0.7.0", only: [:dev, :test], runtime: false},
# Tracing
{:spandex, github: "spandex-project/spandex", branch: "allow-setting-trace-key", override: true},

@ -0,0 +1,13 @@
defmodule Explorer.Repo.Migrations.AddExternalLibrariesToSmartContracts do
use Ecto.Migration
def change do
alter table(:smart_contracts) do
remove(:external_libraries)
end
alter table(:smart_contracts) do
add(:external_libraries, {:array, :map}, default: [])
end
end
end

@ -1,59 +0,0 @@
defmodule Explorer.Chain.BlockNumberCacheTest do
use Explorer.DataCase
alias Explorer.Chain.BlockNumberCache
setup do
Application.put_env(:explorer, Explorer.Chain.BlockNumberCache, enabled: true)
on_exit(fn ->
Application.put_env(:explorer, Explorer.Chain.BlockNumberCache, enabled: false)
end)
end
describe "max_number/1" do
test "returns max number" do
insert(:block, number: 5)
BlockNumberCache.setup()
assert BlockNumberCache.max_number() == 5
end
end
describe "min_number/1" do
test "returns max number" do
insert(:block, number: 2)
BlockNumberCache.setup()
assert BlockNumberCache.max_number() == 2
end
end
describe "update/1" do
test "updates max number" do
insert(:block, number: 2)
BlockNumberCache.setup()
assert BlockNumberCache.max_number() == 2
assert BlockNumberCache.update(3)
assert BlockNumberCache.max_number() == 3
end
test "updates min number" do
insert(:block, number: 2)
BlockNumberCache.setup()
assert BlockNumberCache.min_number() == 2
assert BlockNumberCache.update(1)
assert BlockNumberCache.min_number() == 1
end
end
end

@ -1,55 +1,55 @@
defmodule Explorer.Chain.BlockCountCacheTest do
defmodule Explorer.Chain.Cache.BlockCountTest do
use Explorer.DataCase
alias Explorer.Chain.BlockCountCache
alias Explorer.Chain.Cache.BlockCount
test "returns default transaction count" do
BlockCountCache.start_link(name: BlockTestCache)
BlockCount.start_link(name: BlockTestCache)
result = BlockCountCache.count(BlockTestCache)
result = BlockCount.count(BlockTestCache)
assert is_nil(result)
end
test "updates cache if initial value is zero" do
BlockCountCache.start_link(name: BlockTestCache)
BlockCount.start_link(name: BlockTestCache)
insert(:block, consensus: true)
insert(:block, consensus: true)
insert(:block, consensus: false)
_result = BlockCountCache.count(BlockTestCache)
_result = BlockCount.count(BlockTestCache)
Process.sleep(1000)
updated_value = BlockCountCache.count(BlockTestCache)
updated_value = BlockCount.count(BlockTestCache)
assert updated_value == 2
end
test "does not update cache if cache period did not pass" do
BlockCountCache.start_link(name: BlockTestCache)
BlockCount.start_link(name: BlockTestCache)
insert(:block, consensus: true)
insert(:block, consensus: true)
insert(:block, consensus: false)
_result = BlockCountCache.count(BlockTestCache)
_result = BlockCount.count(BlockTestCache)
Process.sleep(1000)
updated_value = BlockCountCache.count(BlockTestCache)
updated_value = BlockCount.count(BlockTestCache)
assert updated_value == 2
insert(:block, consensus: true)
insert(:block, consensus: true)
_updated_value = BlockCountCache.count(BlockTestCache)
_updated_value = BlockCount.count(BlockTestCache)
Process.sleep(1000)
updated_value = BlockCountCache.count(BlockTestCache)
updated_value = BlockCount.count(BlockTestCache)
assert updated_value == 2
end

@ -0,0 +1,59 @@
defmodule Explorer.Chain.Cache.BlockNumberTest do
use Explorer.DataCase
alias Explorer.Chain.Cache.BlockNumber
setup do
Application.put_env(:explorer, Explorer.Chain.Cache.BlockNumber, enabled: true)
on_exit(fn ->
Application.put_env(:explorer, Explorer.Chain.Cache.BlockNumber, enabled: false)
end)
end
describe "max_number/1" do
test "returns max number" do
insert(:block, number: 5)
BlockNumber.setup()
assert BlockNumber.max_number() == 5
end
end
describe "min_number/1" do
test "returns max number" do
insert(:block, number: 2)
BlockNumber.setup()
assert BlockNumber.max_number() == 2
end
end
describe "update/1" do
test "updates max number" do
insert(:block, number: 2)
BlockNumber.setup()
assert BlockNumber.max_number() == 2
assert BlockNumber.update(3)
assert BlockNumber.max_number() == 3
end
test "updates min number" do
insert(:block, number: 2)
BlockNumber.setup()
assert BlockNumber.min_number() == 2
assert BlockNumber.update(1)
assert BlockNumber.min_number() == 1
end
end
end

@ -1,7 +1,7 @@
defmodule Explorer.Chain.BlocksCacheTest do
defmodule Explorer.Chain.Cache.BlocksTest do
use Explorer.DataCase
alias Explorer.Chain.BlocksCache
alias Explorer.Chain.Cache.Blocks
alias Explorer.Repo
setup do
@ -14,9 +14,9 @@ defmodule Explorer.Chain.BlocksCacheTest do
test "adds a new value to cache" do
block = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards])
BlocksCache.update(block)
Blocks.update(block)
assert BlocksCache.blocks() == [block]
assert Blocks.blocks() == [block]
end
test "adds a new elements removing the oldest one" do
@ -25,43 +25,43 @@ defmodule Explorer.Chain.BlocksCacheTest do
|> Enum.map(fn number ->
block = insert(:block, number: number)
BlocksCache.update(block)
Blocks.update(block)
block.number
end)
new_block = insert(:block, number: 70)
BlocksCache.update(new_block)
Blocks.update(new_block)
new_blocks = blocks |> List.replace_at(0, new_block.number) |> Enum.sort() |> Enum.reverse()
assert Enum.map(BlocksCache.blocks(), & &1.number) == new_blocks
assert Enum.map(Blocks.blocks(), & &1.number) == new_blocks
end
test "does not add too old blocks" do
block = insert(:block, number: 100_000) |> Repo.preload([:transactions, [miner: :names], :rewards])
old_block = insert(:block, number: 1_000)
BlocksCache.update(block)
BlocksCache.update(old_block)
Blocks.update(block)
Blocks.update(old_block)
assert BlocksCache.blocks() == [block]
assert Blocks.blocks() == [block]
end
test "adds missing element" do
block1 = insert(:block, number: 10)
block2 = insert(:block, number: 4)
BlocksCache.update(block1)
BlocksCache.update(block2)
Blocks.update(block1)
Blocks.update(block2)
assert Enum.count(BlocksCache.blocks()) == 2
assert Enum.count(Blocks.blocks()) == 2
block3 = insert(:block, number: 6)
BlocksCache.update(block3)
Blocks.update(block3)
assert Enum.map(BlocksCache.blocks(), & &1.number) == [10, 6, 4]
assert Enum.map(Blocks.blocks(), & &1.number) == [10, 6, 4]
end
end
@ -69,16 +69,16 @@ defmodule Explorer.Chain.BlocksCacheTest do
test "updates cache" do
block = insert(:block)
BlocksCache.update(block)
Blocks.update(block)
block1 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards])
block2 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards])
new_blocks = [block1, block2]
BlocksCache.rewrite_cache(new_blocks)
Blocks.rewrite_cache(new_blocks)
assert BlocksCache.blocks() == [block2, block1]
assert Blocks.blocks() == [block2, block1]
end
end
end

@ -0,0 +1,54 @@
defmodule Explorer.Chain.Cache.TransactionCountTest do
use Explorer.DataCase
alias Explorer.Chain.Cache.TransactionCount
test "returns default transaction count" do
TransactionCount.start_link([[], [name: TestCache]])
result = TransactionCount.value(TestCache)
assert is_nil(result)
end
test "updates cache if initial value is zero" do
TransactionCount.start_link([[], [name: TestCache]])
insert(:transaction)
insert(:transaction)
_result = TransactionCount.value(TestCache)
Process.sleep(1000)
updated_value = TransactionCount.value(TestCache)
assert updated_value == 2
end
test "does not update cache if cache period did not pass" do
TransactionCount.start_link([[], [name: TestCache]])
insert(:transaction)
insert(:transaction)
_result = TransactionCount.value(TestCache)
Process.sleep(1000)
updated_value = TransactionCount.value(TestCache)
assert updated_value == 2
insert(:transaction)
insert(:transaction)
_updated_value = TransactionCount.value(TestCache)
Process.sleep(1000)
updated_value = TransactionCount.value(TestCache)
assert updated_value == 2
end
end

@ -1,7 +1,7 @@
defmodule Explorer.Chain.TransactionsCacheTest do
defmodule Explorer.Chain.Cache.TransactionsTest do
use Explorer.DataCase
alias Explorer.Chain.TransactionsCache
alias Explorer.Chain.Cache.Transactions
alias Explorer.Repo
@size 51
@ -10,9 +10,9 @@ defmodule Explorer.Chain.TransactionsCacheTest do
test "adds a new value to a new cache with preloads" do
transaction = insert(:transaction) |> preload_all()
TransactionsCache.update(transaction)
Transactions.update(transaction)
assert TransactionsCache.take(1) == [transaction]
assert Transactions.take(1) == [transaction]
end
test "adds several elements, removing the oldest when necessary" do
@ -23,9 +23,9 @@ defmodule Explorer.Chain.TransactionsCacheTest do
insert(:transaction) |> with_block(block)
end)
TransactionsCache.update(transactions)
Transactions.update(transactions)
assert TransactionsCache.all() == Enum.reverse(preload_all(transactions))
assert Transactions.all() == Enum.reverse(preload_all(transactions))
more_transactions =
(@size + 1)..(@size + 10)
@ -34,14 +34,14 @@ defmodule Explorer.Chain.TransactionsCacheTest do
insert(:transaction) |> with_block(block)
end)
TransactionsCache.update(more_transactions)
Transactions.update(more_transactions)
kept_transactions =
Enum.reverse(transactions ++ more_transactions)
|> Enum.take(@size)
|> preload_all()
assert TransactionsCache.take(@size) == kept_transactions
assert Transactions.take(@size) == kept_transactions
end
test "does not add a transaction too old when full" do
@ -52,28 +52,28 @@ defmodule Explorer.Chain.TransactionsCacheTest do
insert(:transaction) |> with_block(block)
end)
TransactionsCache.update(transactions)
Transactions.update(transactions)
loaded_transactions = Enum.reverse(preload_all(transactions))
assert TransactionsCache.all() == loaded_transactions
assert Transactions.all() == loaded_transactions
block = insert(:block, number: 1)
insert(:transaction) |> with_block(block) |> TransactionsCache.update()
insert(:transaction) |> with_block(block) |> Transactions.update()
assert TransactionsCache.all() == loaded_transactions
assert Transactions.all() == loaded_transactions
end
test "adds intermediate transactions" do
blocks = 1..10 |> Map.new(fn n -> {n, insert(:block, number: n)} end)
insert(:transaction) |> with_block(blocks[1]) |> TransactionsCache.update()
insert(:transaction) |> with_block(blocks[10]) |> TransactionsCache.update()
insert(:transaction) |> with_block(blocks[1]) |> Transactions.update()
insert(:transaction) |> with_block(blocks[10]) |> Transactions.update()
assert TransactionsCache.size() == 2
assert Transactions.size() == 2
insert(:transaction) |> with_block(blocks[5]) |> TransactionsCache.update()
insert(:transaction) |> with_block(blocks[5]) |> Transactions.update()
assert TransactionsCache.size() == 3
assert Transactions.size() == 3
end
end

@ -1,54 +0,0 @@
defmodule Explorer.Chain.TransactionCountCacheTest do
use Explorer.DataCase
alias Explorer.Chain.TransactionCountCache
test "returns default transaction count" do
TransactionCountCache.start_link([[], [name: TestCache]])
result = TransactionCountCache.value(TestCache)
assert is_nil(result)
end
test "updates cache if initial value is zero" do
TransactionCountCache.start_link([[], [name: TestCache]])
insert(:transaction)
insert(:transaction)
_result = TransactionCountCache.value(TestCache)
Process.sleep(1000)
updated_value = TransactionCountCache.value(TestCache)
assert updated_value == 2
end
test "does not update cache if cache period did not pass" do
TransactionCountCache.start_link([[], [name: TestCache]])
insert(:transaction)
insert(:transaction)
_result = TransactionCountCache.value(TestCache)
Process.sleep(1000)
updated_value = TransactionCountCache.value(TestCache)
assert updated_value == 2
insert(:transaction)
insert(:transaction)
_updated_value = TransactionCountCache.value(TestCache)
Process.sleep(1000)
updated_value = TransactionCountCache.value(TestCache)
assert updated_value == 2
end
end

@ -286,4 +286,18 @@ defmodule Explorer.Chain.TransactionTest do
assert Transaction.decoded_input_data(transaction) == {:ok, "60fe47b1", "set(uint256 x)", [{"x", "uint256", 10}]}
end
end
describe "Poison.encode!/1" do
test "encodes transaction input" do
assert %{
insert(:transaction)
| input: %Explorer.Chain.Data{
bytes:
<<169, 5, 156, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 108, 45, 196, 42, 228, 149, 239, 119,
191, 128, 248>>
}
}
|> Poison.encode!()
end
end
end

@ -70,7 +70,7 @@ defmodule Explorer.ChainTest do
describe "address_to_logs/2" do
test "fetches logs" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction1 =
:transaction
@ -86,11 +86,11 @@ defmodule Explorer.ChainTest do
insert(:log, transaction: transaction2, index: 2, address: address)
assert Enum.count(Chain.address_to_logs(address)) == 2
assert Enum.count(Chain.address_to_logs(address_hash)) == 2
end
test "paginates logs" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -105,15 +105,15 @@ defmodule Explorer.ChainTest do
paging_options1 = %PagingOptions{page_size: 1}
[_log] = Chain.address_to_logs(address, paging_options: paging_options1)
[_log] = Chain.address_to_logs(address_hash, paging_options: paging_options1)
paging_options2 = %PagingOptions{page_size: 60, key: {transaction.block_number, transaction.index, log1.index}}
assert Enum.count(Chain.address_to_logs(address, paging_options: paging_options2)) == 50
assert Enum.count(Chain.address_to_logs(address_hash, paging_options: paging_options2)) == 50
end
test "searches logs by topic when the first topic matches" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction1 =
:transaction
@ -129,13 +129,13 @@ defmodule Explorer.ChainTest do
insert(:log, transaction: transaction2, index: 2, address: address, first_topic: "test")
[found_log] = Chain.address_to_logs(address, topic: "test")
[found_log] = Chain.address_to_logs(address_hash, topic: "test")
assert found_log.transaction.hash == transaction2.hash
end
test "searches logs by topic when the fourth topic matches" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction1 =
:transaction
@ -151,7 +151,7 @@ defmodule Explorer.ChainTest do
insert(:log, transaction: transaction2, index: 2, address: address)
[found_log] = Chain.address_to_logs(address, topic: "test")
[found_log] = Chain.address_to_logs(address_hash, topic: "test")
assert found_log.transaction.hash == transaction1.hash
end
@ -159,15 +159,15 @@ defmodule Explorer.ChainTest do
describe "address_to_transactions_with_rewards/2" do
test "without transactions" do
address = insert(:address)
%Address{hash: address_hash} = insert(:address)
assert Repo.aggregate(Transaction, :count, :hash) == 0
assert [] == Chain.address_to_transactions_with_rewards(address)
assert [] == Chain.address_to_transactions_with_rewards(address_hash)
end
test "with from transactions" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -176,12 +176,12 @@ defmodule Explorer.ChainTest do
|> Repo.preload(:token_transfers)
assert [transaction] ==
Chain.address_to_transactions_with_rewards(address, direction: :from)
Chain.address_to_transactions_with_rewards(address_hash, direction: :from)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to transactions" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -190,12 +190,12 @@ defmodule Explorer.ChainTest do
|> Repo.preload(:token_transfers)
assert [transaction] ==
Chain.address_to_transactions_with_rewards(address, direction: :to)
Chain.address_to_transactions_with_rewards(address_hash, direction: :to)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to and from transactions and direction: :from" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -205,12 +205,12 @@ defmodule Explorer.ChainTest do
# only contains "from" transaction
assert [transaction] ==
Chain.address_to_transactions_with_rewards(address, direction: :from)
Chain.address_to_transactions_with_rewards(address_hash, direction: :from)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to and from transactions and direction: :to" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -219,12 +219,12 @@ defmodule Explorer.ChainTest do
|> Repo.preload(:token_transfers)
assert [transaction] ==
Chain.address_to_transactions_with_rewards(address, direction: :to)
Chain.address_to_transactions_with_rewards(address_hash, direction: :to)
|> Repo.preload([:block, :to_address, :from_address])
end
test "with to and from transactions and no :direction option" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
block = insert(:block)
transaction1 =
@ -240,7 +240,7 @@ defmodule Explorer.ChainTest do
|> Repo.preload(:token_transfers)
assert [transaction2, transaction1] ==
Chain.address_to_transactions_with_rewards(address)
Chain.address_to_transactions_with_rewards(address_hash)
|> Repo.preload([:block, :to_address, :from_address])
end
@ -259,11 +259,11 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index
)
assert [] == Chain.address_to_transactions_with_rewards(address)
assert [] == Chain.address_to_transactions_with_rewards(address.hash)
end
test "returns transactions that have token transfers for the given to_address" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -277,12 +277,12 @@ defmodule Explorer.ChainTest do
)
assert [transaction.hash] ==
Chain.address_to_transactions_with_rewards(address)
Chain.address_to_transactions_with_rewards(address_hash)
|> Enum.map(& &1.hash)
end
test "returns just the token transfers related to the given address" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -303,7 +303,7 @@ defmodule Explorer.ChainTest do
)
transaction =
address
address_hash
|> Chain.address_to_transactions_with_rewards()
|> List.first()
@ -344,7 +344,7 @@ defmodule Explorer.ChainTest do
)
transaction =
contract_address
contract_address.hash
|> Chain.address_to_transactions_with_rewards()
|> List.first()
@ -360,7 +360,8 @@ defmodule Explorer.ChainTest do
end
test "returns all token transfers when the given address is the token contract address" do
contract_address = insert(:address, contract_code: Factory.data("contract_code"))
%Address{hash: contract_address_hash} =
contract_address = insert(:address, contract_code: Factory.data("contract_code"))
transaction =
:transaction
@ -381,7 +382,7 @@ defmodule Explorer.ChainTest do
transaction: transaction
)
transaction = Chain.address_to_transactions_with_rewards(contract_address) |> List.first()
transaction = Chain.address_to_transactions_with_rewards(contract_address_hash) |> List.first()
assert Enum.count(transaction.token_transfers) == 2
end
@ -427,7 +428,7 @@ defmodule Explorer.ChainTest do
)
transactions_hashes =
paul
paul.hash
|> Chain.address_to_transactions_with_rewards()
|> Enum.map(& &1.hash)
@ -436,7 +437,7 @@ defmodule Explorer.ChainTest do
end
test "with transactions can be paginated" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
second_page_hashes =
2
@ -450,7 +451,7 @@ defmodule Explorer.ChainTest do
|> with_block()
assert second_page_hashes ==
address
address_hash
|> Chain.address_to_transactions_with_rewards(
paging_options: %PagingOptions{
key: {block_number, index},
@ -462,7 +463,7 @@ defmodule Explorer.ChainTest do
end
test "returns results in reverse chronological order by block number and transaction index" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
a_block = insert(:block, number: 6000)
@ -499,7 +500,7 @@ defmodule Explorer.ChainTest do
|> with_block(b_block)
result =
address
address_hash
|> Chain.address_to_transactions_with_rewards()
|> Enum.map(& &1.hash)
@ -525,7 +526,7 @@ defmodule Explorer.ChainTest do
address_type: :emission_funds
)
assert [{_, _}] = Chain.address_to_transactions_with_rewards(block.miner)
assert [{_, _}] = Chain.address_to_transactions_with_rewards(block.miner.hash)
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: false)
end
@ -554,7 +555,7 @@ defmodule Explorer.ChainTest do
|> with_block()
|> Repo.preload(:token_transfers)
assert [_, {_, _}] = Chain.address_to_transactions_with_rewards(block.miner, direction: :from)
assert [_, {_, _}] = Chain.address_to_transactions_with_rewards(block.miner.hash, direction: :from)
Application.put_env(:block_scout_web, BlockScoutWeb.Chain, has_emission_funds: false)
end
@ -578,7 +579,7 @@ defmodule Explorer.ChainTest do
address_type: :emission_funds
)
assert [] == Chain.address_to_transactions_with_rewards(block.miner)
assert [] == Chain.address_to_transactions_with_rewards(block.miner.hash)
end
end
@ -590,7 +591,7 @@ defmodule Explorer.ChainTest do
|> insert(nonce: 100, from_address: address)
|> with_block(insert(:block, number: 1000))
assert Chain.total_transactions_sent_by_address(address) == 101
assert Chain.total_transactions_sent_by_address(address.hash) == 101
end
test "returns 0 when the address did not send transactions" do
@ -600,7 +601,7 @@ defmodule Explorer.ChainTest do
|> insert(nonce: 100, to_address: address)
|> with_block(insert(:block, number: 1000))
assert Chain.total_transactions_sent_by_address(address) == 0
assert Chain.total_transactions_sent_by_address(address.hash) == 0
end
end
@ -707,15 +708,15 @@ defmodule Explorer.ChainTest do
describe "address_to_incoming_transaction_count/1" do
test "without transactions" do
address = insert(:address)
%Address{hash: address_hash} = insert(:address)
assert Chain.address_to_incoming_transaction_count(address) == 0
assert Chain.address_to_incoming_transaction_count(address_hash) == 0
end
test "with transactions" do
%Transaction{to_address: to_address} = insert(:transaction)
assert Chain.address_to_incoming_transaction_count(to_address) == 1
assert Chain.address_to_incoming_transaction_count(to_address.hash) == 1
end
end
@ -1575,20 +1576,20 @@ defmodule Explorer.ChainTest do
describe "get_blocks_validated_by_address/2" do
test "returns nothing when there are no blocks" do
address = insert(:address)
%Address{hash: address_hash} = insert(:address)
assert [] = Chain.get_blocks_validated_by_address(address)
assert [] = Chain.get_blocks_validated_by_address(address_hash)
end
test "returns the blocks validated by a specified address" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
another_address = insert(:address)
block = insert(:block, miner: address, miner_hash: address.hash)
insert(:block, miner: another_address, miner_hash: another_address.hash)
results =
address
address_hash
|> Chain.get_blocks_validated_by_address()
|> Enum.map(& &1.hash)
@ -1596,20 +1597,20 @@ defmodule Explorer.ChainTest do
end
test "with blocks can be paginated" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
first_page_block = insert(:block, miner: address, miner_hash: address.hash, number: 0)
second_page_block = insert(:block, miner: address, miner_hash: address.hash, number: 2)
assert [first_page_block.number] ==
[paging_options: %PagingOptions{key: {1}, page_size: 1}]
|> Chain.get_blocks_validated_by_address(address)
|> Chain.get_blocks_validated_by_address(address_hash)
|> Enum.map(& &1.number)
|> Enum.reverse()
assert [second_page_block.number] ==
[paging_options: %PagingOptions{key: {3}, page_size: 1}]
|> Chain.get_blocks_validated_by_address(address)
|> Chain.get_blocks_validated_by_address(address_hash)
|> Enum.map(& &1.number)
|> Enum.reverse()
end
@ -1674,7 +1675,7 @@ defmodule Explorer.ChainTest do
)
result =
address
address.hash
|> Chain.address_to_internal_transactions()
|> Enum.map(&{&1.transaction_hash, &1.index})
@ -1683,7 +1684,7 @@ defmodule Explorer.ChainTest do
end
test "loads associations in necessity_by_association" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
block = insert(:block, number: 2000)
transaction =
@ -1714,7 +1715,7 @@ defmodule Explorer.ChainTest do
transaction: %Transaction{}
}
| _
] = Chain.address_to_internal_transactions(address)
] = Chain.address_to_internal_transactions(address_hash)
assert [
%InternalTransaction{
@ -1725,7 +1726,7 @@ defmodule Explorer.ChainTest do
| _
] =
Chain.address_to_internal_transactions(
address,
address_hash,
necessity_by_association: %{
[from_address: :names] => :optional,
[to_address: :names] => :optional,
@ -1844,7 +1845,7 @@ defmodule Explorer.ChainTest do
)
result =
address
address.hash
|> Chain.address_to_internal_transactions()
|> Enum.map(&{&1.transaction_hash, &1.index})
@ -1968,7 +1969,7 @@ defmodule Explorer.ChainTest do
{second_transaction_hash, second_index},
{first_transaction_hash, first_index}
] ==
address
address.hash
|> Chain.address_to_internal_transactions(
paging_options: %PagingOptions{key: {6001, 3, 2}, page_size: 8}
)
@ -1981,7 +1982,7 @@ defmodule Explorer.ChainTest do
{second_transaction_hash, second_index},
{first_transaction_hash, first_index}
] ==
address
address.hash
|> Chain.address_to_internal_transactions(
paging_options: %PagingOptions{key: {6000, 0, 1}, page_size: 8}
)
@ -1994,7 +1995,7 @@ defmodule Explorer.ChainTest do
{second_transaction_hash, second_index},
{first_transaction_hash, first_index}
] ==
address
address.hash
|> Chain.address_to_internal_transactions(
paging_options: %PagingOptions{key: {6000, -1, -1}, page_size: 8}
)
@ -2002,7 +2003,7 @@ defmodule Explorer.ChainTest do
# block number <
assert [] ==
address
address.hash
|> Chain.address_to_internal_transactions(
paging_options: %PagingOptions{key: {2000, -1, -1}, page_size: 8}
)
@ -2010,7 +2011,7 @@ defmodule Explorer.ChainTest do
end
test "excludes internal transactions of type `call` when they are alone in the parent transaction" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -2025,11 +2026,11 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index
)
assert Enum.empty?(Chain.address_to_internal_transactions(address))
assert Enum.empty?(Chain.address_to_internal_transactions(address_hash))
end
test "includes internal transactions of type `create` even when they are alone in the parent transaction" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction =
:transaction
@ -2046,7 +2047,7 @@ defmodule Explorer.ChainTest do
transaction_index: transaction.index
)
actual = Enum.at(Chain.address_to_internal_transactions(address), 0)
actual = Enum.at(Chain.address_to_internal_transactions(address_hash), 0)
assert {actual.transaction_hash, actual.index} == {expected.transaction_hash, expected.index}
end

@ -4,12 +4,14 @@ defmodule Explorer.GraphQLTest do
import Explorer.Factory
alias Explorer.{GraphQL, Repo}
alias Explorer.Chain.Address
describe "address_to_transactions_query/1" do
test "with address hash with zero transactions" do
result =
:address
|> insert()
|> Map.get(:hash)
|> GraphQL.address_to_transactions_query()
|> Repo.all()
@ -17,12 +19,12 @@ defmodule Explorer.GraphQLTest do
end
test "with matching 'to_address_hash'" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction = insert(:transaction, to_address: address)
insert(:transaction)
[found_transaction] =
address
address_hash
|> GraphQL.address_to_transactions_query()
|> Repo.all()
@ -30,12 +32,12 @@ defmodule Explorer.GraphQLTest do
end
test "with matching 'from_address_hash'" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction = insert(:transaction, from_address: address)
insert(:transaction)
[found_transaction] =
address
address_hash
|> GraphQL.address_to_transactions_query()
|> Repo.all()
@ -43,12 +45,12 @@ defmodule Explorer.GraphQLTest do
end
test "with matching 'created_contract_address_hash'" do
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
transaction = insert(:transaction, created_contract_address: address)
insert(:transaction)
[found_transaction] =
address
address_hash
|> GraphQL.address_to_transactions_query()
|> Repo.all()
@ -60,7 +62,7 @@ defmodule Explorer.GraphQLTest do
second_block = insert(:block)
third_block = insert(:block)
address = insert(:address)
%Address{hash: address_hash} = address = insert(:address)
3
|> insert_list(:transaction, from_address: address)
@ -75,7 +77,7 @@ defmodule Explorer.GraphQLTest do
|> with_block(first_block)
found_transactions =
address
address_hash
|> GraphQL.address_to_transactions_query()
|> Repo.all()

@ -86,5 +86,59 @@ defmodule Explorer.Market.History.Source.CryptoCompareTest do
assert :error == CryptoCompare.fetch_history(3)
end
test "rejects empty prices", %{bypass: bypass} do
json = """
{
"Response": "Success",
"Type": 100,
"Aggregated": false,
"Data": [
{
"time": 1524528000,
"close": 0,
"high": 9741.91,
"low": 8957.68,
"open": 0,
"volumefrom": 136352.05,
"volumeto": 1276464750.74
},
{
"time": 1524614400,
"close": 0,
"high": 9765.23,
"low": 8757.06,
"open": 0,
"volumefrom": 192797.41,
"volumeto": 1779806222.98
},
{
"time": 1524700800,
"close": 8804.32,
"high": 8965.84,
"low": 8669.38,
"open": 8873.57,
"volumefrom": 74704.5,
"volumeto": 661168891
}
],
"TimeTo": 1524700800,
"TimeFrom": 1523836800,
"FirstValueInArray": true,
"ConversionType": {
"type": "direct",
"conversionSymbol": ""
}
}
"""
Bypass.expect(bypass, fn conn -> Conn.resp(conn, 200, json) end)
expected = [
%{closing_price: Decimal.from_float(8804.32), date: ~D[2018-04-26], opening_price: Decimal.from_float(8873.57)}
]
assert {:ok, expected} == CryptoCompare.fetch_history(3)
end
end
end

@ -9,8 +9,8 @@ defmodule Explorer.Market.MarketHistoryCacheTest do
Supervisor.restart_child(Explorer.Supervisor, {ConCache, MarketHistoryCache.cache_name()})
on_exit(fn ->
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
end)
:ok

@ -6,12 +6,12 @@ defmodule Explorer.MarketTest do
alias Explorer.Repo
setup do
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
on_exit(fn ->
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
end)
:ok
@ -72,6 +72,25 @@ defmodule Explorer.MarketTest do
assert missing_records == %{}
end
test "doesn't replace existing records with zeros" do
date = ~D[2018-04-01]
{:ok, old_record} =
Repo.insert(%MarketHistory{date: date, closing_price: Decimal.new(1), opening_price: Decimal.new(1)})
new_record = %{
date: date,
closing_price: Decimal.new(0),
opening_price: Decimal.new(0)
}
Market.bulk_insert_history([new_record])
fetched_record = Repo.get_by(MarketHistory, date: date)
assert fetched_record.closing_price == old_record.closing_price
assert fetched_record.opening_price == old_record.opening_price
end
test "overrides existing records on date conflict" do
date = ~D[2018-04-01]
Repo.insert(%MarketHistory{date: date})

@ -39,11 +39,11 @@ defmodule Explorer.DataCase do
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()})
end
Explorer.Chain.BlockNumberCache.setup()
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()})
Explorer.Chain.Cache.BlockNumber.setup()
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()})
:ok
end

@ -11,7 +11,9 @@ defmodule Indexer.Block.Fetcher do
alias EthereumJSONRPC.{Blocks, FetchedBeneficiaries}
alias Explorer.Chain
alias Explorer.Chain.{Address, Block, BlockNumberCache, BlocksCache, Hash, Import, Transaction, TransactionsCache}
alias Explorer.Chain.{Address, Block, Hash, Import, Transaction}
alias Explorer.Chain.Cache.Blocks, as: BlocksCache
alias Explorer.Chain.Cache.{BlockNumber, Transactions}
alias Indexer.Block.Fetcher.Receipts
alias Indexer.Fetcher.{
@ -185,13 +187,13 @@ defmodule Indexer.Block.Fetcher do
max_block = Enum.max_by(blocks, fn block -> block.number end)
min_block = Enum.min_by(blocks, fn block -> block.number end)
BlockNumberCache.update(max_block.number)
BlockNumberCache.update(min_block.number)
BlockNumber.update(max_block.number)
BlockNumber.update(min_block.number)
BlocksCache.update_blocks(blocks)
end
defp update_transactions_cache(transactions) do
TransactionsCache.update(transactions)
Transactions.update(transactions)
end
def import(

@ -17,8 +17,9 @@ defmodule Indexer.Fetcher.CoinBalanceOnDemand do
alias EthereumJSONRPC.FetchedBalances
alias Explorer.{Chain, Repo}
alias Explorer.Chain.{Address, BlockNumberCache}
alias Explorer.Chain.Address
alias Explorer.Chain.Address.CoinBalance
alias Explorer.Chain.Cache.BlockNumber
alias Explorer.Counters.AverageBlockTime
alias Indexer.Fetcher.CoinBalance, as: CoinBalanceFetcher
alias Timex.Duration
@ -161,7 +162,7 @@ defmodule Indexer.Fetcher.CoinBalanceOnDemand do
end
defp latest_block_number do
BlockNumberCache.max_number()
BlockNumber.max_number()
end
defp stale_balance_window(block_number) do

@ -42,6 +42,7 @@
"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_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
"ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"},
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []},
"excoveralls": {:git, "https://github.com/KronicDeth/excoveralls.git", "0a859b68851eeba9b43eba59fbc8f9098299cfe1", [branch: "circle-workflows"]},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]},
@ -66,6 +67,7 @@
"makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"math": {:hex, :math, "0.3.0", "e14e7291115201cb155a3567e66d196bf5088a6f55b030d598107d7ae934a11c", [:mix], []},
"meck": {:hex, :meck, "0.8.12", "1f7b1a9f5d12c511848fec26bbefd09a21e1432eadb8982d9a8aceb9891a3cf2", [:rebar3], [], "hexpm"},
"memento": {:hex, :memento, "0.3.1", "b2909390820550d8b90b68ec96f9e15ff8a45a28b6f97fa4a62ef50e87c2f9d9", [:mix], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
@ -98,6 +100,7 @@
"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_process_collector": {:hex, :prometheus_process_collector, "1.4.0", "6dbd39e3165b9ef1c94a7a820e9ffe08479f949dcdd431ed4aaea7b250eebfde", [:rebar3], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
"qrcode": {:hex, :qrcode, "0.1.4", "544dc67ba42eed5ebce3d2a691d053387937740561d251f83f0a067917fae2dc", [:mix], [], "hexpm"},
"que": {:hex, :que, "0.10.1", "788ed0ec92ed69bdf9cfb29bf41a94ca6355b8d44959bd0669cf706e557ac891", [:mix], [{:ex_utils, "~> 0.1.6", [hex: :ex_utils, repo: "hexpm", optional: false]}, {:memento, "~> 0.3.0", [hex: :memento, repo: "hexpm", optional: false]}], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"set_locale": {:git, "https://github.com/minifast/set_locale.git", "da9ae029642bc0fbd9212c2aaf86c0adca70c084", [branch: "master"]},
"sobelow": {:hex, :sobelow, "0.7.4", "228cc6185b448b63ecc88429b43e864e8dd570e8e09f2d04b3aa71894db1bdbb", [:mix], [], "hexpm"},

Loading…
Cancel
Save