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

@ -1,10 +1,10 @@
## Current
### Features
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
### 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
- [#2299](https://github.com/poanetwork/blockscout/pull/2299) - fix interpolation in error message
- [#2303](https://github.com/poanetwork/blockscout/pull/2303) - fix transaction csv download link
@ -13,11 +13,14 @@
### Chore
- [#2325](https://github.com/poanetwork/blockscout/pull/2325) - Reduce function input to address' hash only where possible
- [#2323](https://github.com/poanetwork/blockscout/pull/2323) - Group Explorer caches
- [#2305](https://github.com/poanetwork/blockscout/pull/2305) - Improve Address controllers
- [#2302](https://github.com/poanetwork/blockscout/pull/2302) - fix names for xDai source
- [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment
- [#2307](https://github.com/poanetwork/blockscout/pull/2307) - add GoJoy to README
- [#2293](https://github.com/poanetwork/blockscout/pull/2293) - remove request idle timeout configuration
## 2.0.1-beta

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -42,6 +42,7 @@
"ex_doc": {:hex, :ex_doc, "0.19.2", "6f4081ccd9ed081b6dc0bd5af97a41e87f5554de469e7d76025fba535180565f", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ex_machina": {:hex, :ex_machina, "2.2.2", "d84217a6fb7840ff771d2561b8aa6d74a0d8968e4b10ecc0d7e9890dc8fb1c6a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
"ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
"ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"},
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []},
"excoveralls": {:git, "https://github.com/KronicDeth/excoveralls.git", "0a859b68851eeba9b43eba59fbc8f9098299cfe1", [branch: "circle-workflows"]},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]},
@ -66,6 +67,7 @@
"makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"math": {:hex, :math, "0.3.0", "e14e7291115201cb155a3567e66d196bf5088a6f55b030d598107d7ae934a11c", [:mix], []},
"meck": {:hex, :meck, "0.8.12", "1f7b1a9f5d12c511848fec26bbefd09a21e1432eadb8982d9a8aceb9891a3cf2", [:rebar3], [], "hexpm"},
"memento": {:hex, :memento, "0.3.1", "b2909390820550d8b90b68ec96f9e15ff8a45a28b6f97fa4a62ef50e87c2f9d9", [:mix], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
@ -98,6 +100,7 @@
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
"prometheus_process_collector": {:hex, :prometheus_process_collector, "1.4.0", "6dbd39e3165b9ef1c94a7a820e9ffe08479f949dcdd431ed4aaea7b250eebfde", [:rebar3], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
"qrcode": {:hex, :qrcode, "0.1.4", "544dc67ba42eed5ebce3d2a691d053387937740561d251f83f0a067917fae2dc", [:mix], [], "hexpm"},
"que": {:hex, :que, "0.10.1", "788ed0ec92ed69bdf9cfb29bf41a94ca6355b8d44959bd0669cf706e557ac891", [:mix], [{:ex_utils, "~> 0.1.6", [hex: :ex_utils, repo: "hexpm", optional: false]}, {:memento, "~> 0.3.0", [hex: :memento, repo: "hexpm", optional: false]}], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"set_locale": {:git, "https://github.com/minifast/set_locale.git", "da9ae029642bc0fbd9212c2aaf86c0adca70c084", [branch: "master"]},
"sobelow": {:hex, :sobelow, "0.7.4", "228cc6185b448b63ecc88429b43e864e8dd570e8e09f2d04b3aa71894db1bdbb", [:mix], [], "hexpm"},

Loading…
Cancel
Save