Merge branch 'master' into pp-limit-input-to-address-hash

pull/2325/head
Victor Baranov 5 years ago committed by GitHub
commit 302ac49553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .dialyzer-ignore
  2. 5
      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. 20
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
  10. 4
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
  11. 36
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  12. 1
      apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
  13. 8
      apps/block_scout_web/lib/block_scout_web/router.ex
  14. 26
      apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
  15. 14
      apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex
  16. 6
      apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
  17. 77
      apps/block_scout_web/priv/gettext/default.pot
  18. 83
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  19. 4
      apps/block_scout_web/test/support/conn_case.ex
  20. 4
      apps/block_scout_web/test/support/feature_case.ex
  21. 2
      apps/explorer/config/config.exs
  22. 2
      apps/explorer/config/test.exs
  23. 26
      apps/explorer/lib/explorer/application.ex
  24. 41
      apps/explorer/lib/explorer/chain.ex
  25. 5
      apps/explorer/lib/explorer/chain/address.ex
  26. 2
      apps/explorer/lib/explorer/chain/cache/block_count.ex
  27. 2
      apps/explorer/lib/explorer/chain/cache/block_number.ex
  28. 2
      apps/explorer/lib/explorer/chain/cache/blocks.ex
  29. 2
      apps/explorer/lib/explorer/chain/cache/net_version.ex
  30. 2
      apps/explorer/lib/explorer/chain/cache/transaction_count.ex
  31. 2
      apps/explorer/lib/explorer/chain/cache/transactions.ex
  32. 2
      apps/explorer/lib/explorer/chain/events/publisher.ex
  33. 4
      apps/explorer/lib/explorer/chain/events/subscriber.ex
  34. 6
      apps/explorer/lib/explorer/chain/smart_contract.ex
  35. 12
      apps/explorer/lib/explorer/chain/smart_contract/external_library.ex
  36. 5
      apps/explorer/lib/explorer/chain/supply/rsk.ex
  37. 13
      apps/explorer/lib/explorer/market/history/source/crypto_compare.ex
  38. 7
      apps/explorer/lib/explorer/market/market.ex
  39. 23
      apps/explorer/lib/explorer/smart_contract/publisher.ex
  40. 23
      apps/explorer/lib/explorer/smart_contract/publisher_worker.ex
  41. 1
      apps/explorer/mix.exs
  42. 13
      apps/explorer/priv/repo/migrations/20190709103104_add_external_libraries_to_smart_contracts.exs
  43. 59
      apps/explorer/test/explorer/chain/block_number_cache_test.exs
  44. 24
      apps/explorer/test/explorer/chain/cache/block_count_test.exs
  45. 59
      apps/explorer/test/explorer/chain/cache/block_number_test.exs
  46. 36
      apps/explorer/test/explorer/chain/cache/blocks_test.exs
  47. 54
      apps/explorer/test/explorer/chain/cache/transaction_count_test.exs
  48. 34
      apps/explorer/test/explorer/chain/cache/transactions_test.exs
  49. 54
      apps/explorer/test/explorer/chain/transaction_count_cache_test.exs
  50. 54
      apps/explorer/test/explorer/market/history/source/crypto_compare_test.exs
  51. 4
      apps/explorer/test/explorer/market/market_history_cache_test.exs
  52. 27
      apps/explorer/test/explorer/market/market_test.exs
  53. 10
      apps/explorer/test/support/data_case.ex
  54. 10
      apps/indexer/lib/indexer/block/fetcher.ex
  55. 5
      apps/indexer/lib/indexer/fetcher/coin_balance_on_demand.ex
  56. 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/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: 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/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,10 +1,10 @@
## Current ## Current
### Features ### Features
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint - [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
### Fixes ### Fixes
- [#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 - [#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 - [#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 - [#2303](https://github.com/poanetwork/blockscout/pull/2303) - fix transaction csv download link
@ -13,11 +13,14 @@
### Chore ### Chore
- [#2325](https://github.com/poanetwork/blockscout/pull/2325) - Reduce function input to address' hash only where possible - [#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 - [#2305](https://github.com/poanetwork/blockscout/pull/2305) - Improve Address controllers
- [#2302](https://github.com/poanetwork/blockscout/pull/2302) - fix names for xDai source - [#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 - [#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 - [#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 ## 2.0.1-beta

@ -34,6 +34,7 @@ import './pages/transactions'
import './pages/favorites' import './pages/favorites'
import './pages/network-search' import './pages/network-search'
import './pages/layout' import './pages/layout'
import './pages/verification_form'
import './pages/admin/tasks.js' import './pages/admin/tasks.js'
@ -46,7 +47,6 @@ import './lib/market_history_chart'
import './lib/pending_transactions_toggle' import './lib/pending_transactions_toggle'
import './lib/pretty_json' import './lib/pretty_json'
import './lib/reload_button' import './lib/reload_button'
import './lib/smart_contract/new_smart_contract_form'
import './lib/smart_contract/read_only_functions' import './lib/smart_contract/read_only_functions'
import './lib/smart_contract/wei_ether_converter' import './lib/smart_contract/wei_ether_converter'
import './lib/stop_propagation' 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 # Configures the endpoint
config :block_scout_web, BlockScoutWeb.Endpoint, config :block_scout_web, BlockScoutWeb.Endpoint,
instrumenters: [BlockScoutWeb.Prometheus.Instrumenter, SpandexPhoenix.Instrumenter], instrumenters: [BlockScoutWeb.Prometheus.Instrumenter, SpandexPhoenix.Instrumenter],
http: [
protocol_options: [
idle_timeout: 90_000
]
],
url: [ url: [
host: System.get_env("BLOCKSCOUT_HOST") || "localhost", host: System.get_env("BLOCKSCOUT_HOST") || "localhost",
path: System.get_env("NETWORK_PATH") || "/" path: System.get_env("NETWORK_PATH") || "/"

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

@ -11,7 +11,7 @@ defmodule BlockScoutWeb.AddressChannel do
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Phoenix.View 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 def join("addresses:" <> address_hash, _params, socket) do
{:ok, %{}, assign(socket, :address_hash, address_hash)} {:ok, %{}, assign(socket, :address_hash, address_hash)}
@ -58,6 +58,18 @@ defmodule BlockScoutWeb.AddressChannel do
end end
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 def handle_out("count", %{count: count}, socket) do
Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale) Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale)

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

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

@ -4,11 +4,13 @@ defmodule BlockScoutWeb.Notifier do
""" """
alias Absinthe.Subscription alias Absinthe.Subscription
alias BlockScoutWeb.Endpoint alias BlockScoutWeb.{AddressContractVerificationView, Endpoint}
alias Explorer.{Chain, Market, Repo} alias Explorer.{Chain, Market, Repo}
alias Explorer.Chain.{Address, InternalTransaction, Transaction} alias Explorer.Chain.{Address, InternalTransaction, Transaction}
alias Explorer.Counters.AverageBlockTime alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token 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 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()}) 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) Enum.each(address_coin_balances, &broadcast_address_coin_balance/1)
end 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 def handle_event({:chain_event, :block_rewards, :realtime, rewards}) do
if Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:has_emission_funds] do if Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:has_emission_funds] do
broadcast_rewards(rewards) broadcast_rewards(rewards)

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

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

@ -52,17 +52,6 @@
<dd class="col-sm-8 col-md-10"><%= @address.smart_contract.constructor_arguments %></dd> <dd class="col-sm-8 col-md-10"><%= @address.smart_contract.constructor_arguments %></dd>
</dl> </dl>
<% end %> <% 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> </div>
<hr/> <hr/>
<section> <section>
@ -109,7 +98,7 @@
</div> </div>
<% {:ok, contract_code} -> %> <% {:ok, contract_code} -> %>
<div class="d-flex justify-content-between align-items-baseline"> <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"> <button type="button" class="btn-line" id="button" data-clipboard-text="<%= contract_code %>" aria-label="copy contract creation code">
<%= gettext "Copy Contract Byte Code" %> <%= gettext "Copy Contract Byte Code" %>
</button> </button>
@ -120,6 +109,19 @@
<% end %> <% end %>
</section> </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>
</div> </div>
</section> </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"> <div class="new-smart-contract-form">
<h1 class="smart-contract-title"><%= gettext "New Smart Contract Verification" %></h1> <h1 class="smart-contract-title"><%= gettext "New Smart Contract Verification" %></h1>
<%= form_for @changeset, <%= form_for @changeset,
address_verify_contract_path(@conn, :create, @conn.params["address_id"]), address_contract_verification_path(@conn, :create),
[], [],
fn f -> %> fn f -> %>
@ -240,13 +246,13 @@
</span> </span>
<%= gettext("Loading....") %> <%= gettext("Loading....") %>
</button> </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" %> <%= reset gettext("Reset"), class: "btn-line mr-2 js-smart-contract-form-reset" %>
<%= <%=
link( link(
gettext("Cancel"), gettext("Cancel"),
class: "btn-no-border", class: "btn-no-border",
to: address_contract_path(@conn, :index, @conn.params["address_id"]) to: address_contract_path(@conn, :index, @address_hash)
) )
%> %>
</div> </div>

@ -21,6 +21,12 @@ defmodule BlockScoutWeb.AddressContractView do
def format_optimization_text(true), do: gettext("true") def format_optimization_text(true), do: gettext("true")
def format_optimization_text(false), do: gettext("false") 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 def contract_lines_with_index(contract_source_code) do
contract_lines = String.split(contract_source_code, "\n") contract_lines = String.split(contract_source_code, "\n")

@ -197,7 +197,7 @@ msgid "Blocks Validated"
msgstr "" msgstr ""
#, elixir-format #, 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 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
@ -225,7 +225,7 @@ msgid "Code"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Compiler"
msgstr "" msgstr ""
@ -258,12 +258,12 @@ msgid "Connection Lost, click to load newer validations"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract ABI"
msgstr "" msgstr ""
#, elixir-format #, 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 #: lib/block_scout_web/views/address_view.ex:97
msgid "Contract Address" msgid "Contract Address"
msgstr "" msgstr ""
@ -286,7 +286,7 @@ msgid "Contract Creation"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Name"
msgstr "" msgstr ""
@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract source code"
msgstr "" msgstr ""
@ -560,7 +560,7 @@ msgid "Name"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "No"
msgstr "" msgstr ""
@ -651,7 +651,7 @@ msgid "Request URL"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Reset"
msgstr "" msgstr ""
@ -939,7 +939,7 @@ msgid "Verify & Publish"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Verify & publish"
msgstr "" msgstr ""
@ -989,7 +989,7 @@ msgid "Wei"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Yes"
msgstr "" msgstr ""
@ -1062,7 +1062,7 @@ msgid "Loading..."
msgstr "" msgstr ""
#, elixir-format #, 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...." msgid "Loading...."
msgstr "" msgstr ""
@ -1405,17 +1405,17 @@ msgid "Support"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy ABI"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy Source Code"
msgstr "" msgstr ""
@ -1425,7 +1425,7 @@ msgid "Genesis Block"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Libraries"
msgstr "" msgstr ""
@ -1488,7 +1488,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:35 #: 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" msgid "EVM Version"
msgstr "" msgstr ""
@ -1519,7 +1519,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:45 #: 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" msgid "Optimization runs"
msgstr "" msgstr ""
@ -1585,27 +1585,27 @@ msgid "Block Details"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, 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." msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, 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." msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
@ -1655,35 +1655,35 @@ msgid "Topic"
msgstr "" msgstr ""
#, elixir-format #, 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)" msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Enter the Solidity Contract Code"
msgstr "" msgstr ""
#, elixir-format #, 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:133
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:149 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:155
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:171 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:177
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:193 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:199
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:215 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:221
msgid "Library Address" msgid "Library Address"
msgstr "" msgstr ""
#, elixir-format #, 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:123
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:145
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:167
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:183 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:189
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:205 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:211
msgid "Library Name" msgid "Library Name"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "New Smart Contract Verification"
msgstr "" msgstr ""
@ -1769,7 +1769,7 @@ msgid "ERC-721 "
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "External libraries"
msgstr "" msgstr ""
@ -1797,3 +1797,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:12 #: 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." msgid "Use the search box to find a hosted network, or select from the list of available networks below."
msgstr "" 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 "" msgstr ""
#, elixir-format #, 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 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
@ -225,7 +225,7 @@ msgid "Code"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Compiler"
msgstr "" msgstr ""
@ -258,12 +258,12 @@ msgid "Connection Lost, click to load newer validations"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract ABI"
msgstr "" msgstr ""
#, elixir-format #, 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 #: lib/block_scout_web/views/address_view.ex:97
msgid "Contract Address" msgid "Contract Address"
msgstr "" msgstr ""
@ -286,7 +286,7 @@ msgid "Contract Creation"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Name"
msgstr "" msgstr ""
@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract source code"
msgstr "" msgstr ""
@ -560,7 +560,7 @@ msgid "Name"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "No"
msgstr "" msgstr ""
@ -651,7 +651,7 @@ msgid "Request URL"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Reset"
msgstr "" msgstr ""
@ -674,7 +674,7 @@ msgstr ""
#, elixir-format #, 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" msgid "Search tokens"
msgstr "" msgstr ""
@ -877,7 +877,7 @@ msgid "Transactions"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Transactions sent"
msgstr "" msgstr ""
@ -923,7 +923,7 @@ msgid "Validated Transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tile.html.eex:23 #: lib/block_scout_web/templates/address/_tile.html.eex:35
msgid "Validations" msgid "Validations"
msgstr "" msgstr ""
@ -939,7 +939,7 @@ msgid "Verify & Publish"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Verify & publish"
msgstr "" msgstr ""
@ -989,7 +989,7 @@ msgid "Wei"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Yes"
msgstr "" msgstr ""
@ -1062,7 +1062,7 @@ msgid "Loading..."
msgstr "" msgstr ""
#, elixir-format #, 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...." msgid "Loading...."
msgstr "" msgstr ""
@ -1405,17 +1405,17 @@ msgid "Support"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy ABI"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy Source Code"
msgstr "" msgstr ""
@ -1425,7 +1425,7 @@ msgid "Genesis Block"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Libraries"
msgstr "" msgstr ""
@ -1488,7 +1488,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:35 #: 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" msgid "EVM Version"
msgstr "" msgstr ""
@ -1519,7 +1519,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:45 #: 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" msgid "Optimization runs"
msgstr "" msgstr ""
@ -1585,27 +1585,27 @@ msgid "Block Details"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, 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." msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Copy Contract Byte Code"
msgstr "" msgstr ""
#, elixir-format #, 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." msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
@ -1655,35 +1655,35 @@ msgid "Topic"
msgstr "" msgstr ""
#, elixir-format #, 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)" msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "Enter the Solidity Contract Code"
msgstr "" msgstr ""
#, elixir-format #, 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:133
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:149 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:155
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:171 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:177
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:193 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:199
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:215 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:221
msgid "Library Address" msgid "Library Address"
msgstr "" msgstr ""
#, elixir-format #, 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:123
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:145
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:167
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:183 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:189
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:205 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:211
msgid "Library Name" msgid "Library Name"
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "New Smart Contract Verification"
msgstr "" msgstr ""
@ -1769,7 +1769,7 @@ msgid "ERC-721 "
msgstr "" msgstr ""
#, elixir-format #, 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" msgid "External libraries"
msgstr "" msgstr ""
@ -1797,3 +1797,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:12 #: 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." msgid "Use the search box to find a hosted network, or select from the list of available networks below."
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
msgid "Connection Lost"
msgstr ""

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

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

@ -19,7 +19,7 @@ config :explorer,
config :explorer, Explorer.Counters.AverageBlockTime, enabled: true 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, config :explorer, Explorer.ExchangeRates.Source.CoinMarketCap,
pages: String.to_integer(System.get_env("COINMARKETCAP_PAGES") || "10") 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.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 config :explorer, Explorer.KnownTokens, enabled: false, store: :ets

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

@ -31,9 +31,6 @@ defmodule Explorer.Chain do
Address.CurrentTokenBalance, Address.CurrentTokenBalance,
Address.TokenBalance, Address.TokenBalance,
Block, Block,
BlockCountCache,
BlockNumberCache,
BlocksCache,
Data, Data,
DecompiledSmartContract, DecompiledSmartContract,
Hash, Hash,
@ -45,12 +42,19 @@ defmodule Explorer.Chain do
Token, Token,
TokenTransfer, TokenTransfer,
Transaction, Transaction,
TransactionCountCache,
TransactionsCache,
Wei Wei
} }
alias Explorer.Chain.Block.{EmissionReward, Reward} alias Explorer.Chain.Block.{EmissionReward, Reward}
alias Explorer.Chain.Cache.{
BlockCount,
BlockNumber,
Blocks,
TransactionCount,
Transactions
}
alias Explorer.Chain.Import.Runner alias Explorer.Chain.Import.Runner
alias Explorer.Counters.AddressesWithBalanceCounter alias Explorer.Counters.AddressesWithBalanceCounter
alias Explorer.Market.MarketHistoryCache alias Explorer.Market.MarketHistoryCache
@ -256,7 +260,7 @@ defmodule Explorer.Chain do
def address_to_logs(address_hash, options \\ []) when is_list(options) do def address_to_logs(address_hash, options \\ []) when is_list(options) do
paging_options = Keyword.get(options, :paging_options) || %PagingOptions{page_size: 50} 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 = base_query =
from(log in Log, from(log in Log,
@ -1154,7 +1158,7 @@ defmodule Explorer.Chain do
""" """
@spec indexed_ratio() :: Decimal.t() @spec indexed_ratio() :: Decimal.t()
def indexed_ratio do def indexed_ratio do
{min, max} = BlockNumberCache.min_and_max_numbers() {min, max} = BlockNumber.min_and_max_numbers()
case {min, max} do case {min, max} do
{0, 0} -> {0, 0} ->
@ -1236,12 +1240,12 @@ defmodule Explorer.Chain do
block_type = Keyword.get(options, :block_type, "Block") block_type = Keyword.get(options, :block_type, "Block")
if block_type == "Block" && !paging_options.key do if block_type == "Block" && !paging_options.key do
if BlocksCache.enough_elements?(paging_options.page_size) do if Blocks.enough_elements?(paging_options.page_size) do
BlocksCache.blocks(paging_options.page_size) Blocks.blocks(paging_options.page_size)
else else
elements = fetch_blocks(block_type, paging_options, necessity_by_association) elements = fetch_blocks(block_type, paging_options, necessity_by_association)
BlocksCache.rewrite_cache(elements) Blocks.rewrite_cache(elements)
elements elements
end end
@ -2000,11 +2004,11 @@ defmodule Explorer.Chain do
if is_nil(paging_options.key) do if is_nil(paging_options.key) do
paging_options.page_size paging_options.page_size
|> TransactionsCache.take_enough() |> Transactions.take_enough()
|> case do |> case do
nil -> nil ->
transactions = fetch_recent_collated_transactions(paging_options, necessity_by_association) transactions = fetch_recent_collated_transactions(paging_options, necessity_by_association)
TransactionsCache.update(transactions) Transactions.update(transactions)
transactions transactions
transactions -> transactions ->
@ -2149,7 +2153,7 @@ defmodule Explorer.Chain do
""" """
@spec transaction_estimated_count() :: non_neg_integer() @spec transaction_estimated_count() :: non_neg_integer()
def transaction_estimated_count do def transaction_estimated_count do
cached_value = TransactionCountCache.value() cached_value = TransactionCount.value()
if is_nil(cached_value) do if is_nil(cached_value) do
%Postgrex.Result{rows: [[rows]]} = %Postgrex.Result{rows: [[rows]]} =
@ -2168,7 +2172,7 @@ defmodule Explorer.Chain do
""" """
@spec block_estimated_count() :: non_neg_integer() @spec block_estimated_count() :: non_neg_integer()
def block_estimated_count do def block_estimated_count do
cached_value = BlockCountCache.count() cached_value = BlockCount.count()
if is_nil(cached_value) do if is_nil(cached_value) do
%Postgrex.Result{rows: [[count]]} = Repo.query!("SELECT reltuples FROM pg_class WHERE relname = 'blocks';") %Postgrex.Result{rows: [[count]]} = Repo.query!("SELECT reltuples FROM pg_class WHERE relname = 'blocks';")
@ -2416,8 +2420,13 @@ defmodule Explorer.Chain do
naming the address for reference. naming the address for reference.
""" """
@spec create_smart_contract(map()) :: {:ok, SmartContract.t()} | {:error, Ecto.Changeset.t()} @spec create_smart_contract(map()) :: {:ok, SmartContract.t()} | {:error, Ecto.Changeset.t()}
def create_smart_contract(attrs \\ %{}) do def create_smart_contract(attrs \\ %{}, external_libraries \\ []) do
smart_contract_changeset = SmartContract.changeset(%SmartContract{}, attrs) new_contract = %SmartContract{}
smart_contract_changeset =
new_contract
|> SmartContract.changeset(attrs)
|> Changeset.put_change(:external_libraries, external_libraries)
insert_result = insert_result =
Multi.new() Multi.new()

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

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

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

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

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

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

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

@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Publisher do
Publishes events related to the Chain context. 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 def broadcast(_data, false), do: :ok

@ -3,9 +3,9 @@ defmodule Explorer.Chain.Events.Subscriber do
Subscribes to events related to the Chain context. 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 @allowed_events ~w(exchange_rate)a

@ -13,6 +13,7 @@ defmodule Explorer.Chain.SmartContract do
use Explorer.Schema use Explorer.Schema
alias Explorer.Chain.{Address, ContractMethod, DecompiledSmartContract, Hash} alias Explorer.Chain.{Address, ContractMethod, DecompiledSmartContract, Hash}
alias Explorer.Chain.SmartContract.ExternalLibrary
alias Explorer.Repo alias Explorer.Repo
@typedoc """ @typedoc """
@ -212,7 +213,7 @@ defmodule Explorer.Chain.SmartContract do
field(:constructor_arguments, :string) field(:constructor_arguments, :string)
field(:evm_version, :string) field(:evm_version, :string)
field(:optimization_runs, :integer) field(:optimization_runs, :integer)
field(:external_libraries, :map) embeds_many(:external_libraries, ExternalLibrary)
field(:abi, {:array, :map}) field(:abi, {:array, :map})
has_many( has_many(
@ -247,8 +248,7 @@ defmodule Explorer.Chain.SmartContract do
:abi, :abi,
:constructor_arguments, :constructor_arguments,
:evm_version, :evm_version,
:optimization_runs, :optimization_runs
:external_libraries
]) ])
|> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash]) |> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash])
|> unique_constraint(: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 EthereumJSONRPC.FetchedBalances
alias Explorer.Chain.Address.CoinBalance alias Explorer.Chain.Address.CoinBalance
alias Explorer.Chain.{Block, BlockNumberCache, Wei} alias Explorer.Chain.{Block, Wei}
alias Explorer.Chain.Cache.BlockNumber
alias Explorer.Repo alias Explorer.Repo
@cache_name :rsk_balance @cache_name :rsk_balance
@ -99,7 +100,7 @@ defmodule Explorer.Chain.Supply.RSK do
def cache_name, do: @cache_name def cache_name, do: @cache_name
defp fetch_circulating_value do defp fetch_circulating_value do
max_number = BlockNumberCache.max_number() max_number = BlockNumber.max_number()
params = [ params = [
%{block_quantity: integer_to_quantity(max_number), hash_data: "0x0000000000000000000000000000000001000006"} %{block_quantity: integer_to_quantity(max_number), hash_data: "0x0000000000000000000000000000000001000006"}

@ -24,7 +24,12 @@ defmodule Explorer.Market.History.Source.CryptoCompare do
case HTTPoison.get(url, headers) do case HTTPoison.get(url, headers) do
{:ok, %Response{body: body, status_code: 200}} -> {:ok, %Response{body: body, status_code: 200}} ->
{:ok, format_data(body)} result =
body
|> format_data()
|> reject_zeros()
{:ok, result}
_ -> _ ->
:error :error
@ -67,4 +72,10 @@ defmodule Explorer.Market.History.Source.CryptoCompare do
"#{base_url()}/data/histoday?#{URI.encode_query(query_params)}" "#{base_url()}/data/histoday?#{URI.encode_query(query_params)}"
end 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 end

@ -40,7 +40,12 @@ defmodule Explorer.Market do
@doc false @doc false
def bulk_insert_history(records) do 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 end
def add_price(%{symbol: symbol} = token) do 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 case Verifier.evaluate_authenticity(address_hash, params_with_external_libaries) do
{:ok, %{abi: abi}} -> {:ok, %{abi: abi}} ->
publish_smart_contract(address_hash, params, abi) publish_smart_contract(address_hash, params_with_external_libaries, abi)
{:error, error} -> {:error, error} ->
{:error, unverified_smart_contract(address_hash, params, error)} {:error, unverified_smart_contract(address_hash, params_with_external_libaries, error)}
end end
end end
defp publish_smart_contract(address_hash, params, abi) do defp publish_smart_contract(address_hash, params, abi) do
address_hash attrs = address_hash |> attributes(params, abi)
|> attributes(params, abi)
|> Chain.create_smart_contract() Chain.create_smart_contract(attrs, attrs.external_libraries)
end end
defp unverified_smart_contract(address_hash, params, error) do defp unverified_smart_contract(address_hash, params, error) do
@ -64,6 +64,8 @@ defmodule Explorer.SmartContract.Publisher do
nil nil
end end
prepared_external_libraries = prepare_external_libraies(params["external_libraries"])
%{ %{
address_hash: address_hash, address_hash: address_hash,
name: params["name"], name: params["name"],
@ -73,11 +75,20 @@ defmodule Explorer.SmartContract.Publisher do
optimization: params["optimization"], optimization: params["optimization"],
contract_source_code: params["contract_source_code"], contract_source_code: params["contract_source_code"],
constructor_arguments: clean_constructor_arguments, constructor_arguments: clean_constructor_arguments,
external_libaries: params["external_libraries"], external_libraries: prepared_external_libraries,
abi: abi abi: abi
} }
end 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 defp add_external_libraries(params, external_libraries) do
clean_external_libraries = clean_external_libraries =
Enum.reduce(1..5, %{}, fn number, acc -> 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 # bypass optional dependency
{:plug_cowboy, "~> 2.0", only: [:dev, :test]}, {:plug_cowboy, "~> 2.0", only: [:dev, :test]},
{:que, "~> 0.10.1"},
{:sobelow, ">= 0.7.0", only: [:dev, :test], runtime: false}, {:sobelow, ">= 0.7.0", only: [:dev, :test], runtime: false},
# Tracing # Tracing
{:spandex, github: "spandex-project/spandex", branch: "allow-setting-trace-key", override: true}, {: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 use Explorer.DataCase
alias Explorer.Chain.BlockCountCache alias Explorer.Chain.Cache.BlockCount
test "returns default transaction count" do 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) assert is_nil(result)
end end
test "updates cache if initial value is zero" do 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: true) insert(:block, consensus: true)
insert(:block, consensus: false) insert(:block, consensus: false)
_result = BlockCountCache.count(BlockTestCache) _result = BlockCount.count(BlockTestCache)
Process.sleep(1000) Process.sleep(1000)
updated_value = BlockCountCache.count(BlockTestCache) updated_value = BlockCount.count(BlockTestCache)
assert updated_value == 2 assert updated_value == 2
end end
test "does not update cache if cache period did not pass" do 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: true) insert(:block, consensus: true)
insert(:block, consensus: false) insert(:block, consensus: false)
_result = BlockCountCache.count(BlockTestCache) _result = BlockCount.count(BlockTestCache)
Process.sleep(1000) Process.sleep(1000)
updated_value = BlockCountCache.count(BlockTestCache) updated_value = BlockCount.count(BlockTestCache)
assert updated_value == 2 assert updated_value == 2
insert(:block, consensus: true) insert(:block, consensus: true)
insert(:block, consensus: true) insert(:block, consensus: true)
_updated_value = BlockCountCache.count(BlockTestCache) _updated_value = BlockCount.count(BlockTestCache)
Process.sleep(1000) Process.sleep(1000)
updated_value = BlockCountCache.count(BlockTestCache) updated_value = BlockCount.count(BlockTestCache)
assert updated_value == 2 assert updated_value == 2
end 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 use Explorer.DataCase
alias Explorer.Chain.BlocksCache alias Explorer.Chain.Cache.Blocks
alias Explorer.Repo alias Explorer.Repo
setup do setup do
@ -14,9 +14,9 @@ defmodule Explorer.Chain.BlocksCacheTest do
test "adds a new value to cache" do test "adds a new value to cache" do
block = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) block = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards])
BlocksCache.update(block) Blocks.update(block)
assert BlocksCache.blocks() == [block] assert Blocks.blocks() == [block]
end end
test "adds a new elements removing the oldest one" do test "adds a new elements removing the oldest one" do
@ -25,43 +25,43 @@ defmodule Explorer.Chain.BlocksCacheTest do
|> Enum.map(fn number -> |> Enum.map(fn number ->
block = insert(:block, number: number) block = insert(:block, number: number)
BlocksCache.update(block) Blocks.update(block)
block.number block.number
end) end)
new_block = insert(:block, number: 70) 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() 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 end
test "does not add too old blocks" do test "does not add too old blocks" do
block = insert(:block, number: 100_000) |> Repo.preload([:transactions, [miner: :names], :rewards]) block = insert(:block, number: 100_000) |> Repo.preload([:transactions, [miner: :names], :rewards])
old_block = insert(:block, number: 1_000) old_block = insert(:block, number: 1_000)
BlocksCache.update(block) Blocks.update(block)
BlocksCache.update(old_block) Blocks.update(old_block)
assert BlocksCache.blocks() == [block] assert Blocks.blocks() == [block]
end end
test "adds missing element" do test "adds missing element" do
block1 = insert(:block, number: 10) block1 = insert(:block, number: 10)
block2 = insert(:block, number: 4) block2 = insert(:block, number: 4)
BlocksCache.update(block1) Blocks.update(block1)
BlocksCache.update(block2) Blocks.update(block2)
assert Enum.count(BlocksCache.blocks()) == 2 assert Enum.count(Blocks.blocks()) == 2
block3 = insert(:block, number: 6) 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
end end
@ -69,16 +69,16 @@ defmodule Explorer.Chain.BlocksCacheTest do
test "updates cache" do test "updates cache" do
block = insert(:block) block = insert(:block)
BlocksCache.update(block) Blocks.update(block)
block1 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) block1 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards])
block2 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) block2 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards])
new_blocks = [block1, block2] 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 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 use Explorer.DataCase
alias Explorer.Chain.TransactionsCache alias Explorer.Chain.Cache.Transactions
alias Explorer.Repo alias Explorer.Repo
@size 51 @size 51
@ -10,9 +10,9 @@ defmodule Explorer.Chain.TransactionsCacheTest do
test "adds a new value to a new cache with preloads" do test "adds a new value to a new cache with preloads" do
transaction = insert(:transaction) |> preload_all() transaction = insert(:transaction) |> preload_all()
TransactionsCache.update(transaction) Transactions.update(transaction)
assert TransactionsCache.take(1) == [transaction] assert Transactions.take(1) == [transaction]
end end
test "adds several elements, removing the oldest when necessary" do test "adds several elements, removing the oldest when necessary" do
@ -23,9 +23,9 @@ defmodule Explorer.Chain.TransactionsCacheTest do
insert(:transaction) |> with_block(block) insert(:transaction) |> with_block(block)
end) 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 = more_transactions =
(@size + 1)..(@size + 10) (@size + 1)..(@size + 10)
@ -34,14 +34,14 @@ defmodule Explorer.Chain.TransactionsCacheTest do
insert(:transaction) |> with_block(block) insert(:transaction) |> with_block(block)
end) end)
TransactionsCache.update(more_transactions) Transactions.update(more_transactions)
kept_transactions = kept_transactions =
Enum.reverse(transactions ++ more_transactions) Enum.reverse(transactions ++ more_transactions)
|> Enum.take(@size) |> Enum.take(@size)
|> preload_all() |> preload_all()
assert TransactionsCache.take(@size) == kept_transactions assert Transactions.take(@size) == kept_transactions
end end
test "does not add a transaction too old when full" do 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) insert(:transaction) |> with_block(block)
end) end)
TransactionsCache.update(transactions) Transactions.update(transactions)
loaded_transactions = Enum.reverse(preload_all(transactions)) loaded_transactions = Enum.reverse(preload_all(transactions))
assert TransactionsCache.all() == loaded_transactions assert Transactions.all() == loaded_transactions
block = insert(:block, number: 1) 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 end
test "adds intermediate transactions" do test "adds intermediate transactions" do
blocks = 1..10 |> Map.new(fn n -> {n, insert(:block, number: n)} end) 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[1]) |> Transactions.update()
insert(:transaction) |> with_block(blocks[10]) |> TransactionsCache.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
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

@ -86,5 +86,59 @@ defmodule Explorer.Market.History.Source.CryptoCompareTest do
assert :error == CryptoCompare.fetch_history(3) assert :error == CryptoCompare.fetch_history(3)
end 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
end end

@ -9,8 +9,8 @@ defmodule Explorer.Market.MarketHistoryCacheTest do
Supervisor.restart_child(Explorer.Supervisor, {ConCache, MarketHistoryCache.cache_name()}) Supervisor.restart_child(Explorer.Supervisor, {ConCache, MarketHistoryCache.cache_name()})
on_exit(fn -> on_exit(fn ->
Supervisor.terminate_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.BlocksCache.cache_name()}) Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
end) end)
:ok :ok

@ -6,12 +6,12 @@ defmodule Explorer.MarketTest do
alias Explorer.Repo alias Explorer.Repo
setup do setup do
Supervisor.terminate_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.BlocksCache.cache_name()}) Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
on_exit(fn -> on_exit(fn ->
Supervisor.terminate_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.BlocksCache.cache_name()}) Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
end) end)
:ok :ok
@ -72,6 +72,25 @@ defmodule Explorer.MarketTest do
assert missing_records == %{} assert missing_records == %{}
end 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 test "overrides existing records on date conflict" do
date = ~D[2018-04-01] date = ~D[2018-04-01]
Repo.insert(%MarketHistory{date: date}) Repo.insert(%MarketHistory{date: date})

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

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

@ -17,8 +17,9 @@ defmodule Indexer.Fetcher.CoinBalanceOnDemand do
alias EthereumJSONRPC.FetchedBalances alias EthereumJSONRPC.FetchedBalances
alias Explorer.{Chain, Repo} alias Explorer.{Chain, Repo}
alias Explorer.Chain.{Address, BlockNumberCache} alias Explorer.Chain.Address
alias Explorer.Chain.Address.CoinBalance alias Explorer.Chain.Address.CoinBalance
alias Explorer.Chain.Cache.BlockNumber
alias Explorer.Counters.AverageBlockTime alias Explorer.Counters.AverageBlockTime
alias Indexer.Fetcher.CoinBalance, as: CoinBalanceFetcher alias Indexer.Fetcher.CoinBalance, as: CoinBalanceFetcher
alias Timex.Duration alias Timex.Duration
@ -161,7 +162,7 @@ defmodule Indexer.Fetcher.CoinBalanceOnDemand do
end end
defp latest_block_number do defp latest_block_number do
BlockNumberCache.max_number() BlockNumber.max_number()
end end
defp stale_balance_window(block_number) do 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_doc": {:hex, :ex_doc, "0.19.2", "6f4081ccd9ed081b6dc0bd5af97a41e87f5554de469e7d76025fba535180565f", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ex_machina": {:hex, :ex_machina, "2.2.2", "d84217a6fb7840ff771d2561b8aa6d74a0d8968e4b10ecc0d7e9890dc8fb1c6a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"}, "ex_machina": {:hex, :ex_machina, "2.2.2", "d84217a6fb7840ff771d2561b8aa6d74a0d8968e4b10ecc0d7e9890dc8fb1c6a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
"ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"}, "ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
"ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"},
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []}, "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []},
"excoveralls": {:git, "https://github.com/KronicDeth/excoveralls.git", "0a859b68851eeba9b43eba59fbc8f9098299cfe1", [branch: "circle-workflows"]}, "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]}]}, "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"}, "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], []}, "math": {:hex, :math, "0.3.0", "e14e7291115201cb155a3567e66d196bf5088a6f55b030d598107d7ae934a11c", [:mix], []},
"meck": {:hex, :meck, "0.8.12", "1f7b1a9f5d12c511848fec26bbefd09a21e1432eadb8982d9a8aceb9891a3cf2", [:rebar3], [], "hexpm"}, "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], []}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"}, "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "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_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"}, "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"}, "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"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"set_locale": {:git, "https://github.com/minifast/set_locale.git", "da9ae029642bc0fbd9212c2aaf86c0adca70c084", [branch: "master"]}, "set_locale": {:git, "https://github.com/minifast/set_locale.git", "da9ae029642bc0fbd9212c2aaf86c0adca70c084", [branch: "master"]},
"sobelow": {:hex, :sobelow, "0.7.4", "228cc6185b448b63ecc88429b43e864e8dd570e8e09f2d04b3aa71894db1bdbb", [:mix], [], "hexpm"}, "sobelow": {:hex, :sobelow, "0.7.4", "228cc6185b448b63ecc88429b43e864e8dd570e8e09f2d04b3aa71894db1bdbb", [:mix], [], "hexpm"},

Loading…
Cancel
Save