commit
302ac49553
@ -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() |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
@ -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 |
||||||
""" |
""" |
@ -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 |
@ -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 |
@ -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 |
@ -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,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 |
|
Loading…
Reference in new issue