diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fe38ef08b..89bbf472d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- [#7298](https://github.com/blockscout/blockscout/pull/7298) - Add changes to support force email verification - [#7416](https://github.com/blockscout/blockscout/pull/7416) - Add option to disable reCAPTCHA - [#6694](https://github.com/blockscout/blockscout/pull/6694) - Add withdrawals support (EIP-4895) - [#7355](https://github.com/blockscout/blockscout/pull/7355) - Add endpoint for token info import diff --git a/apps/block_scout_web/assets/css/main-page.scss b/apps/block_scout_web/assets/css/main-page.scss index 690d78b7e6..7aeb2d2cea 100644 --- a/apps/block_scout_web/assets/css/main-page.scss +++ b/apps/block_scout_web/assets/css/main-page.scss @@ -5,6 +5,11 @@ display: none; } +a.disabled { + pointer-events: none; + opacity: 0.65; +} + /* This file is for your main application css. */ // Bootstrap Core CSS @@ -14,6 +19,7 @@ @import "theme/variables"; +@import "~bootstrap/scss/close"; @import "~bootstrap/scss/root"; @import "~bootstrap/scss/reboot"; @import "~bootstrap/scss/grid"; diff --git a/apps/block_scout_web/assets/js/lib/modals.js b/apps/block_scout_web/assets/js/lib/modals.js index 3c862ea4a9..ec0f83771d 100644 --- a/apps/block_scout_web/assets/js/lib/modals.js +++ b/apps/block_scout_web/assets/js/lib/modals.js @@ -25,7 +25,7 @@ export function currentModal () { return $currentModal } -export function openModal ($modal, unclosable) { +export function openModal ($modal, unclosable, onHideCallback = null) { // Hide all tooltips before showing a modal, // since they are sticking on top of modal $('.tooltip').tooltip('hide') @@ -54,6 +54,9 @@ export function openModal ($modal, unclosable) { modalLocked = true } } + if (onHideCallback) { + $($currentModal).on('hidden.bs.modal', onHideCallback) + } } export function openModalWithMessage ($modal, unclosable, message) { @@ -116,11 +119,11 @@ export function openWarningModal (title, text) { openModal($modal) } -export function openSuccessModal (title, text) { +export function openSuccessModal (title, text, callback = null) { const $modal = $('#successStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').html(text) - openModal($modal) + openModal($modal, false, callback) } export function openQuestionModal (title, text, acceptCallback = null, exceptCallback = null, acceptText = 'Yes', exceptText = 'No') { diff --git a/apps/block_scout_web/assets/js/lib/public_tags_request_form.js b/apps/block_scout_web/assets/js/lib/public_tags_request_form.js index f2794f6918..df59c68cb0 100644 --- a/apps/block_scout_web/assets/js/lib/public_tags_request_form.js +++ b/apps/block_scout_web/assets/js/lib/public_tags_request_form.js @@ -11,7 +11,6 @@ if (index <= 1) { $('.add-form-field').on('click', (event) => { event.preventDefault() - console.log(event) const $container = $('#' + event.currentTarget.dataset.container) // @ts-ignore const index = parseInt($container[0].dataset.index) diff --git a/apps/block_scout_web/assets/js/pages/chain.js b/apps/block_scout_web/assets/js/pages/chain.js index c71eb6b575..858a04b6c1 100644 --- a/apps/block_scout_web/assets/js/pages/chain.js +++ b/apps/block_scout_web/assets/js/pages/chain.js @@ -12,6 +12,7 @@ import { createStore, connectElements } from '../lib/redux_helpers.js' import { batchChannel, showLoader } from '../lib/utils' import listMorph from '../lib/list_morph' import '../app' +import { openErrorModal, openSuccessModal, openWarningModal } from '../lib/modals' const BATCH_THRESHOLD = 6 const BLOCKS_PER_PAGE = 4 @@ -418,3 +419,26 @@ function loadBlocks (store) { function bindBlockErrorMessage (store) { $('[data-selector="chain-block-list"] [data-selector="error-message"]').on('click', _event => loadBlocks(store)) } + +$('a.ajax').on('click', (event) => { + event.preventDefault() + event.currentTarget.classList.add('disabled') + + $.get($(event.currentTarget).attr('href'), () => { + openSuccessModal('Success', 'Email successfully resent', () => { window.location.reload() }) + }).fail((error) => { + if (error.responseJSON && error.responseJSON.message) { + if (error.status === 429) { + openWarningModal('Warning', error.responseJSON.message) + } else { + openErrorModal('Error', error.responseJSON.message, false) + } + } else { + openErrorModal('Error', 'Email resend failed', false) + } + }) + .always(() => { + event.currentTarget.classList.remove('disabled') + }) +} +) diff --git a/apps/block_scout_web/lib/block_scout_web/api_router.ex b/apps/block_scout_web/lib/block_scout_web/api_router.ex index e1325432fb..0a738baf3f 100644 --- a/apps/block_scout_web/lib/block_scout_web/api_router.ex +++ b/apps/block_scout_web/lib/block_scout_web/api_router.ex @@ -46,7 +46,7 @@ defmodule BlockScoutWeb.ApiRouter do plug(RateLimit) end - alias BlockScoutWeb.Account.Api.V1.{AuthenticateController, TagsController, UserController} + alias BlockScoutWeb.Account.Api.V1.{AuthenticateController, EmailController, TagsController, UserController} alias BlockScoutWeb.API.V2 scope "/account/v1", as: :account_v1 do @@ -58,6 +58,10 @@ defmodule BlockScoutWeb.ApiRouter do get("/get_csrf", UserController, :get_csrf) + scope "/email" do + get("/resend", EmailController, :resend_email) + end + scope "/user" do get("/info", UserController, :info) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/authenticate_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/authenticate_controller.ex index 386d082fbc..0c16034d02 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/authenticate_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/authenticate_controller.ex @@ -21,7 +21,7 @@ defmodule BlockScoutWeb.Account.Api.V1.AuthenticateController do {:sensitive_endpoints_api_key, Application.get_env(:block_scout_web, :sensitive_endpoints_api_key)}, {:api_key, ^api_key} <- {:api_key, params["api_key"]}, {:auth, %{id: uid} = current_user} <- {:auth, current_user(conn)}, - {:identity, [%Identity{}]} <- {:identity, UserFromAuth.find_identity(uid)} do + {:identity, %Identity{}} <- {:identity, UserFromAuth.find_identity(uid)} do conn |> put_status(200) |> json(current_user) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/email_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/email_controller.ex new file mode 100644 index 0000000000..b8f2ce7631 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/email_controller.ex @@ -0,0 +1,64 @@ +defmodule BlockScoutWeb.Account.Api.V1.EmailController do + use BlockScoutWeb, :controller + + alias BlockScoutWeb.Models.UserFromAuth + alias Explorer.Account.Identity + alias Explorer.Repo + alias Explorer.ThirdPartyIntegrations.Auth0 + + require Logger + + action_fallback(BlockScoutWeb.Account.Api.V1.FallbackController) + + def resend_email(conn, _params) do + with user <- get_session(conn, :current_user), + {:auth, false} <- {:auth, is_nil(user)}, + {:email_verified, false} <- {:email_verified, user[:email_verified]}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(user[:id])}, + {:interval, true} <- {:interval, check_time_interval(identity.verification_email_sent_at)} do + domain = Application.get_env(:ueberauth, Ueberauth.Strategy.Auth0.OAuth)[:domain] + api_key = Auth0.get_m2m_jwt() + headers = [{"Authorization", "Bearer #{api_key}"}, {"Content-Type", "application/json"}] + url = "https://#{domain}/api/v2/jobs/verification-email" + + body = %{ + "user_id" => user.uid + } + + case HTTPoison.post(url, Jason.encode!(body), headers, []) do + {:ok, %HTTPoison.Response{body: _body, status_code: 201}} -> + identity + |> Identity.changeset(%{verification_email_sent_at: DateTime.utc_now()}) + |> Repo.account_repo().update() + + conn + |> configure_session(drop: true) + |> json(%{message: "Success"}) + + other -> + Logger.error(fn -> ["Error while sending verification email: ", inspect(other)] end) + + conn + |> put_status(500) + |> json(%{message: "Unexpected error"}) + end + end + end + + def check_time_interval(nil), do: true + + def check_time_interval(sent_at) do + interval = Application.get_env(:explorer, Explorer.Account)[:resend_interval] + now = DateTime.utc_now() + + if sent_at + |> DateTime.add(interval, :millisecond) + |> DateTime.compare(now) != :gt do + true + else + sent_at + |> DateTime.add(interval, :millisecond) + |> DateTime.diff(now, :second) + end + end +end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/fallback_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/fallback_controller.ex index 1e7a02bc55..6c6603b53f 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/fallback_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/fallback_controller.ex @@ -75,10 +75,12 @@ defmodule BlockScoutWeb.Account.Api.V1.FallbackController do end def call(conn, {:auth, _}) do + current_user = get_session(conn, :current_user) + conn - |> put_status(:unauthorized) + |> put_status(if(current_user, do: :forbidden, else: :unauthorized)) |> put_view(UserView) - |> render(:message, %{message: "Unauthorized"}) + |> render(:message, %{message: if(current_user, do: "Unverified email", else: "Unauthorized")}) end def call(conn, {:api_key, _}) do @@ -94,4 +96,18 @@ defmodule BlockScoutWeb.Account.Api.V1.FallbackController do |> put_view(UserView) |> render(:message, %{message: "API key not configured on the server"}) end + + def call(conn, {:email_verified, _}) do + conn + |> put_status(:not_found) + |> put_view(UserView) + |> render(:message, %{message: "Your email address already verified"}) + end + + def call(conn, {:interval, remain}) do + conn + |> put_status(:too_many_requests) + |> put_view(UserView) + |> render(:message, %{message: "Email resend is available in #{remain} seconds."}) + end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/tags_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/tags_controller.ex index 7c40a29e6b..3549024f90 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/tags_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/tags_controller.ex @@ -17,7 +17,7 @@ defmodule BlockScoutWeb.Account.Api.V1.TagsController do else uid = current_user(conn).id - with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + with {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.account_repo().preload(identity, :watchlists)}, {:address_hash, {:ok, address_hash}} <- {:address_hash, Address.cast(address_hash)} do @@ -58,7 +58,7 @@ defmodule BlockScoutWeb.Account.Api.V1.TagsController do else uid = current_user(conn).id - with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + with {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.account_repo().preload(identity, :watchlists)}, false <- is_nil(transaction) do diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/user_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/user_controller.ex index 837d64771d..42b67c7c17 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/user_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/api/v1/user_controller.ex @@ -18,7 +18,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def info(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)} do + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)} do conn |> put_status(200) |> render(:user_info, %{identity: identity}) @@ -27,7 +27,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def watchlist(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.account_repo().preload(identity, :watchlists)}, watchlist_with_addresses <- preload_watchlist_addresses(watchlist) do @@ -42,7 +42,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def delete_watchlist(conn, %{"id" => watchlist_address_id}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.account_repo().preload(identity, :watchlists)}, {count, _} <- WatchlistAddress.delete(watchlist_address_id, watchlist.id), @@ -94,7 +94,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do } with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.account_repo().preload(identity, :watchlists)}, {:ok, watchlist_address} <- @@ -151,7 +151,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do } with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.account_repo().preload(identity, :watchlists)}, {:ok, watchlist_address} <- @@ -167,7 +167,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def tags_address(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, address_tags <- TagAddress.get_tags_address_by_identity_id(identity.id) do conn |> put_status(200) @@ -177,7 +177,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def delete_tag_address(conn, %{"id" => tag_id}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {count, _} <- TagAddress.delete(tag_id, identity.id), {:tag_delete, true} <- {:tag_delete, count > 0} do conn @@ -188,7 +188,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def create_tag_address(conn, %{"address_hash" => address_hash, "name" => name}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, address_tag} <- TagAddress.create(%{ name: name, @@ -203,7 +203,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def update_tag_address(conn, %{"id" => tag_id} = attrs) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, address_tag} <- TagAddress.update( reject_nil_map_values(%{ @@ -221,7 +221,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def tags_transaction(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, transaction_tags <- TagTransaction.get_tags_transaction_by_identity_id(identity.id) do conn |> put_status(200) @@ -231,7 +231,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def delete_tag_transaction(conn, %{"id" => tag_id}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {count, _} <- TagTransaction.delete(tag_id, identity.id), {:tag_delete, true} <- {:tag_delete, count > 0} do conn @@ -242,7 +242,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def create_tag_transaction(conn, %{"transaction_hash" => tx_hash, "name" => name}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, transaction_tag} <- TagTransaction.create(%{ name: name, @@ -257,7 +257,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def update_tag_transaction(conn, %{"id" => tag_id} = attrs) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, transaction_tag} <- TagTransaction.update( reject_nil_map_values(%{ @@ -275,7 +275,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def api_keys(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, api_keys <- ApiKey.get_api_keys_by_identity_id(identity.id) do conn |> put_status(200) @@ -285,7 +285,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def delete_api_key(conn, %{"api_key" => api_key_uuid}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {count, _} <- ApiKey.delete(api_key_uuid, identity.id), {:api_key_delete, true} <- {:api_key_delete, count > 0} do conn @@ -296,7 +296,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def create_api_key(conn, %{"name" => api_key_name}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, api_key} <- ApiKey.create(%{name: api_key_name, identity_id: identity.id}) do conn @@ -307,7 +307,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def update_api_key(conn, %{"name" => api_key_name, "api_key" => api_key_value}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, api_key} <- ApiKey.update(%{value: api_key_value, name: api_key_name, identity_id: identity.id}) do conn @@ -318,7 +318,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def custom_abis(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, custom_abis <- CustomABI.get_custom_abis_by_identity_id(identity.id) do conn |> put_status(200) @@ -328,7 +328,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def delete_custom_abi(conn, %{"id" => id}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {count, _} <- CustomABI.delete(id, identity.id), {:custom_abi_delete, true} <- {:custom_abi_delete, count > 0} do conn @@ -339,7 +339,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def create_custom_abi(conn, %{"contract_address_hash" => contract_address_hash, "name" => name, "abi" => abi}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, custom_abi} <- CustomABI.create(%{ name: name, @@ -360,7 +360,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do } = params ) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, custom_abi} <- CustomABI.update( reject_nil_map_values(%{ @@ -379,7 +379,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def public_tags_requests(conn, _params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, public_tags_requests <- PublicTagsRequest.get_public_tags_requests_by_identity_id(identity.id) do conn |> put_status(200) @@ -389,7 +389,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def delete_public_tags_request(conn, %{"id" => id, "remove_reason" => remove_reason}) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:public_tag_delete, true} <- {:public_tag_delete, PublicTagsRequest.mark_as_deleted_public_tags_request(%{ @@ -405,7 +405,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do def create_public_tags_request(conn, params) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, public_tags_request} <- PublicTagsRequest.create(%{ full_name: params["full_name"], @@ -431,7 +431,7 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do } = params ) do with {:auth, %{id: uid}} <- {:auth, current_user(conn)}, - {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)}, + {:identity, %Identity{} = identity} <- {:identity, UserFromAuth.find_identity(uid)}, {:ok, public_tags_request} <- PublicTagsRequest.update( reject_nil_map_values(%{ diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/auth_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/auth_controller.ex index c97ab5fb3a..6d6c926c2c 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/account/auth_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/auth_controller.ex @@ -35,6 +35,11 @@ defmodule BlockScoutWeb.Account.AuthController do def callback(%{assigns: %{ueberauth_auth: auth}} = conn, params) do case UserFromAuth.find_or_create(auth) do + {:ok, %{email_verified: false} = user} -> + conn + |> put_session(:current_user, user) + |> redirect(to: root()) + {:ok, user} -> CSRFProtection.get_csrf_token() @@ -60,7 +65,9 @@ defmodule BlockScoutWeb.Account.AuthController do def current_user(%{private: %{plug_session: %{"current_user" => _}}} = conn) do if Account.enabled?() do - get_session(conn, :current_user) + conn + |> get_session(:current_user) + |> check_email_verification() else nil end @@ -68,6 +75,9 @@ defmodule BlockScoutWeb.Account.AuthController do def current_user(_), do: nil + defp check_email_verification(%{email_verified: true} = session), do: session + defp check_email_verification(_), do: nil + defp root do ConfigHelper.network_path() end diff --git a/apps/block_scout_web/lib/block_scout_web/models/user_from_auth.ex b/apps/block_scout_web/lib/block_scout_web/models/user_from_auth.ex index 058b160540..71cdef5103 100644 --- a/apps/block_scout_web/lib/block_scout_web/models/user_from_auth.ex +++ b/apps/block_scout_web/lib/block_scout_web/models/user_from_auth.ex @@ -11,31 +11,23 @@ defmodule BlockScoutWeb.Models.UserFromAuth do import Ecto.Query, only: [from: 2] - def find_or_create(%Auth{} = auth, api_call? \\ false) do + def find_or_create(%Auth{} = auth) do case find_identity(auth) do - [] -> + nil -> case create_identity(auth) do %Identity{} = identity -> - {:ok, return_value(identity, auth, api_call?)} + {:ok, session_info(auth, identity)} {:error, changeset} -> {:error, changeset} end - [%{} = identity | _] -> + %{} = identity -> update_identity(identity, update_identity_map(auth)) - {:ok, return_value(identity, auth, api_call?)} + {:ok, session_info(auth, identity)} end end - defp return_value(identity, _auth, true) do - identity - end - - defp return_value(identity, auth, false) do - basic_info(auth, identity) - end - defp create_identity(auth) do with {:ok, %Identity{} = identity} <- Repo.account_repo().insert(new_identity(auth)), {:ok, _watchlist} <- add_watchlist(identity) do @@ -68,7 +60,7 @@ defmodule BlockScoutWeb.Models.UserFromAuth do end def find_identity(auth_or_uid) do - Repo.account_repo().all(query_identity(auth_or_uid)) + Repo.account_repo().one(query_identity(auth_or_uid)) end def query_identity(%Auth{} = auth) do @@ -79,7 +71,21 @@ defmodule BlockScoutWeb.Models.UserFromAuth do from(i in Identity, where: i.id == ^id) end - defp basic_info(auth, identity) do + defp session_info( + %Auth{extra: %Ueberauth.Auth.Extra{raw_info: %{user: %{"email_verified" => false}}}} = auth, + identity + ) do + %{ + id: identity.id, + uid: auth.uid, + email: email_from_auth(auth), + nickname: nickname_from_auth(auth), + avatar: avatar_from_auth(auth), + email_verified: false + } + end + + defp session_info(auth, identity) do %{watchlists: [watchlist | _]} = Repo.account_repo().preload(identity, :watchlists) %{ @@ -89,7 +95,8 @@ defmodule BlockScoutWeb.Models.UserFromAuth do name: name_from_auth(auth), nickname: nickname_from_auth(auth), avatar: avatar_from_auth(auth), - watchlist_id: watchlist.id + watchlist_id: watchlist.id, + email_verified: true } end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_account_menu_item.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_account_menu_item.html.eex index 541dcecb45..e7742d231f 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_account_menu_item.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_account_menu_item.html.eex @@ -1,33 +1,37 @@ <%= if Explorer.Account.enabled?() do %> - <%= if @current_user do %> - - <% else %> -
  • - - - <%= render BlockScoutWeb.IconsView, "_accounts_icon.html" %> - - <%= gettext "Sign in" %> - -
  • - <% end %> + <%= if @current_user do %> + + <% else %> +
  • + + + <%= render BlockScoutWeb.IconsView, "_accounts_icon.html" %> + + <%= gettext "Sign in" %> + +
  • + <% end %> <% end %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex index 8f2310b37c..0762d44d33 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex @@ -91,11 +91,15 @@ <% end %> <% end %> - <%= render BlockScoutWeb.LayoutView, "_topnav.html", current_user: Conn.get_session(@conn, :current_user), conn: @conn %> - -
    + <% session = Explorer.Account.enabled?() && Plug.Conn.get_session(@conn, :current_user) %> + <%= render BlockScoutWeb.LayoutView, "_topnav.html", current_user: session, conn: @conn %> + <%= if session && !session[:email_verified] do %> + + <% else %> - + <% end %> + +
    <%= @inner_content %>
    <%= render BlockScoutWeb.LayoutView, "_footer.html", assigns %> diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 6a556a3a59..759f5dd799 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -53,6 +53,11 @@ msgstr "" msgid "%{count} Transactions" msgstr "" +#: lib/block_scout_web/templates/transaction/_actions.html.eex:101 +#, elixir-autogen, elixir-format +msgid "%{qty} of Token ID [%{link_to_id}]" +msgstr "" + #: lib/block_scout_web/templates/chain/_metatags.html.eex:2 #, elixir-autogen, elixir-format msgid "%{subnetwork} %{network} Explorer" @@ -86,6 +91,26 @@ msgstr "" msgid "- We're indexing this chain right now. Some of the counts may be inaccurate." msgstr "" +#: lib/block_scout_web/templates/transaction/not_found.html.eex:8 +#, elixir-autogen, elixir-format +msgid "1. If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page." +msgstr "" + +#: lib/block_scout_web/templates/transaction/not_found.html.eex:9 +#, elixir-autogen, elixir-format +msgid "2. It could still be in the TX Pool of a different node, waiting to be broadcasted." +msgstr "" + +#: lib/block_scout_web/templates/transaction/not_found.html.eex:10 +#, elixir-autogen, elixir-format +msgid "3. During times when the network is busy (i.e during ICOs) it can take a while for your transaction to propagate through the network and for us to index it." +msgstr "" + +#: lib/block_scout_web/templates/transaction/not_found.html.eex:11 +#, elixir-autogen, elixir-format +msgid "4. If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information." +msgstr "" + #: lib/block_scout_web/templates/block/overview.html.eex:195 #, elixir-autogen, elixir-format msgid "64-bit hash of value verifying proof-of-work (note: null for POA chains)." @@ -97,6 +122,11 @@ msgstr "" msgid "A block producer who successfully included the block onto the blockchain." msgstr "" +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "A confirmation email was sent to" +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_common_fields/_library_first.html.eex:4 #, elixir-autogen, elixir-format msgid "A library name called in the .sol file. Multiple libraries (up to " @@ -147,7 +177,7 @@ msgstr "" #: lib/block_scout_web/templates/account/api_key/index.html.eex:7 #: lib/block_scout_web/templates/account/common/_nav.html.eex:16 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:17 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:18 #, elixir-autogen, elixir-format msgid "API keys" msgstr "" @@ -252,7 +282,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:10 #: lib/block_scout_web/templates/account/tag_address/index.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:15 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:16 #, elixir-autogen, elixir-format msgid "Address Tags" msgstr "" @@ -282,6 +312,12 @@ msgstr "" msgid "Addresses" msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:38 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:35 +#, elixir-autogen, elixir-format +msgid "Age" +msgstr "" + #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:26 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28 #: lib/block_scout_web/templates/address_transaction/index.html.eex:22 @@ -310,6 +346,13 @@ msgstr "" msgid "All tokens in the account and total value." msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:41 +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:32 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:38 +#, elixir-autogen, elixir-format +msgid "Amount" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:437 #, elixir-autogen, elixir-format msgid "Amount of" @@ -320,6 +363,11 @@ msgstr "" msgid "Amount of distributed reward. Miners receive a static block reward + Tx fees + uncle fees." msgstr "" +#: lib/block_scout_web/templates/internal_server_error/index.html.eex:8 +#, elixir-autogen, elixir-format +msgid "An unexpected error has occurred. Try reloading the page, or come back soon and try again." +msgstr "" + #: lib/block_scout_web/templates/api_docs/eth_rpc.html.eex:15 #, elixir-autogen, elixir-format msgid "Anything not in this list is not supported. Click on the method to be taken to the documentation for that method, and check the notes section for any potential differences." @@ -365,6 +413,14 @@ msgstr "" msgid "Back to Watch list (Cancel)" msgstr "" +#: lib/block_scout_web/templates/error422/index.html.eex:9 +#: lib/block_scout_web/templates/internal_server_error/index.html.eex:9 +#: lib/block_scout_web/templates/page_not_found/index.html.eex:9 +#: lib/block_scout_web/templates/transaction/not_found.html.eex:13 +#, elixir-autogen, elixir-format +msgid "Back to home" +msgstr "" + #: lib/block_scout_web/templates/account/watchlist/show.html.eex:24 #: lib/block_scout_web/templates/address/overview.html.eex:150 #: lib/block_scout_web/templates/address_token/overview.html.eex:51 @@ -399,6 +455,16 @@ msgstr "" msgid "Base URL:" msgstr "" +#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:2 +#, elixir-autogen, elixir-format +msgid "Beacon chain withdrawals - %{subnetwork} Explorer" +msgstr "" + +#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Beacon chain, Withdrawals, %{subnetwork}, %{coin}" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:472 #, elixir-autogen, elixir-format msgid "Binary data included with the transaction. See input / logs below for additional info." @@ -565,6 +631,11 @@ msgstr "" msgid "Chore Reward" msgstr "" +#: lib/block_scout_web/templates/tokens/index.html.eex:38 +#, elixir-autogen, elixir-format +msgid "Circulating Market Cap" +msgstr "" + #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:137 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:106 #, elixir-autogen, elixir-format @@ -962,7 +1033,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:19 #: lib/block_scout_web/templates/account/custom_abi/form.html.eex:8 #: lib/block_scout_web/templates/account/custom_abi/index.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:18 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:19 #, elixir-autogen, elixir-format msgid "Custom ABI" msgstr "" @@ -1429,11 +1500,21 @@ msgstr "" msgid "Hex (Default)" msgstr "" +#: lib/block_scout_web/templates/transaction/overview.html.eex:204 +#, elixir-autogen, elixir-format +msgid "Highlighted events of the transaction." +msgstr "" + #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:108 #, elixir-autogen, elixir-format msgid "Holders" msgstr "" +#: lib/block_scout_web/templates/tokens/index.html.eex:48 +#, elixir-autogen, elixir-format +msgid "Holders Count" +msgstr "" + #: lib/block_scout_web/templates/api_docs/eth_rpc.html.eex:11 #, elixir-autogen, elixir-format msgid "However, in general, the" @@ -1478,6 +1559,13 @@ msgstr "" msgid "Incoming" msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:29 +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:23 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:23 +#, elixir-autogen, elixir-format +msgid "Index" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:464 #, elixir-autogen, elixir-format msgid "Index position of Transaction in the block." @@ -1518,6 +1606,11 @@ msgstr "" msgid "Internal Transactions" msgstr "" +#: lib/block_scout_web/templates/internal_server_error/index.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Internal server error" +msgstr "" + #: lib/block_scout_web/templates/tokens/inventory/index.html.eex:16 #: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:19 #: lib/block_scout_web/views/tokens/overview_view.ex:42 @@ -1709,6 +1802,11 @@ msgstr "" msgid "Minimum fee required per unit of gas. Fee adjusts based on network congestion." msgstr "" +#: lib/block_scout_web/templates/transaction/_actions.html.eex:92 +#, elixir-autogen, elixir-format +msgid "Mint of %{address} To %{to}" +msgstr "" + #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:223 #, elixir-autogen, elixir-format msgid "Model" @@ -1984,6 +2082,12 @@ msgstr "" msgid "Play" msgstr "" +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:22 +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "Please confirm your email address to use the My Account feature." +msgstr "" + #: lib/block_scout_web/templates/account/watchlist_address/form.html.eex:68 #, elixir-autogen, elixir-format msgid "Please select notification methods:" @@ -2004,6 +2108,11 @@ msgstr "" msgid "Position %{index}" msgstr "" +#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18 +#, elixir-autogen, elixir-format +msgid "Potential matches from contract method database:" +msgstr "" + #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:32 #, elixir-autogen, elixir-format msgid "Potential matches from our contract method database:" @@ -2043,12 +2152,12 @@ msgid "Priority Fees" msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:4 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:13 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:14 #, elixir-autogen, elixir-format msgid "Profile" msgstr "" -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:19 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:20 #, elixir-autogen, elixir-format msgid "Public Tags" msgstr "" @@ -2139,6 +2248,11 @@ msgstr "" msgid "Request a public tag/label" msgstr "" +#: lib/block_scout_web/templates/error422/index.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Request cannot be processed" +msgstr "" + #: lib/block_scout_web/templates/account/public_tags_request/index.html.eex:37 #, elixir-autogen, elixir-format msgid "Request to add public tag" @@ -2149,6 +2263,11 @@ msgstr "" msgid "Request to edit a public tag/label" msgstr "" +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "Resend verification email" +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:112 #: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:38 #: lib/block_scout_web/templates/address_contract_verification_via_multi_part_files/new.html.eex:104 @@ -2201,6 +2320,11 @@ msgstr "" msgid "Save" msgstr "" +#: lib/block_scout_web/templates/transaction/overview.html.eex:206 +#, elixir-autogen, elixir-format +msgid "Scroll to see more" +msgstr "" + #: lib/block_scout_web/templates/address_logs/index.html.eex:16 #: lib/block_scout_web/templates/layout/_search.html.eex:34 #, elixir-autogen, elixir-format @@ -2222,6 +2346,11 @@ msgstr "" msgid "Search tokens" msgstr "" +#: lib/block_scout_web/templates/address_contract_verification_common_fields/_yul_contracts_switcher.html.eex:19 +#, elixir-autogen, elixir-format +msgid "Select Yes if you want to verify Yul contract." +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_common_fields/_include_nightly_builds_field.html.eex:19 #, elixir-autogen, elixir-format msgid "Select yes if you want to show nightly builds." @@ -2273,11 +2402,21 @@ msgstr "" msgid "Shows total assets held in the address" msgstr "" -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:20 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:33 +#, elixir-autogen, elixir-format +msgid "Sign in" +msgstr "" + +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:24 #, elixir-autogen, elixir-format msgid "Sign out" msgstr "" +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:11 +#, elixir-autogen, elixir-format +msgid "Signed in as " +msgstr "" + #: lib/block_scout_web/templates/block/overview.html.eex:114 #, elixir-autogen, elixir-format msgid "Size" @@ -2344,6 +2483,11 @@ msgstr "" msgid "Something went wrong, click to retry." msgstr "" +#: lib/block_scout_web/templates/transaction/not_found.html.eex:6 +#, elixir-autogen, elixir-format +msgid "Sorry, we are unable to locate this transaction hash" +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_via_multi_part_files/new.html.eex:63 #, elixir-autogen, elixir-format msgid "Sources *.sol files" @@ -2500,6 +2644,11 @@ msgstr "" msgid "The total gas amount used in the block and its percentage of gas filled in the block." msgstr "" +#: lib/block_scout_web/templates/withdrawal/index.html.eex:11 +#, elixir-autogen, elixir-format +msgid "There are %{withdrawals_count} withdrawals total that withdrawn %{withdrawals_sum}" +msgstr "" + #: lib/block_scout_web/templates/address_validation/index.html.eex:16 #, elixir-autogen, elixir-format msgid "There are no blocks validated by this address." @@ -2587,11 +2736,31 @@ msgstr "" msgid "There are no verified contracts." msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:54 +#, elixir-autogen, elixir-format +msgid "There are no withdrawals for this address." +msgstr "" + +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:45 +#, elixir-autogen, elixir-format +msgid "There are no withdrawals for this block." +msgstr "" + +#: lib/block_scout_web/templates/withdrawal/index.html.eex:53 +#, elixir-autogen, elixir-format +msgid "There are no withdrawals." +msgstr "" + #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:35 #, elixir-autogen, elixir-format msgid "There is no coin history for this address." msgstr "" +#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:29 +#, elixir-autogen, elixir-format +msgid "There is no decompiled contracts for this address." +msgstr "" + #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:21 #: lib/block_scout_web/templates/chain/show.html.eex:9 #, elixir-autogen, elixir-format @@ -2628,6 +2797,11 @@ msgstr "" msgid "This is useful to allow sending requests to blockscout without having to change anything about the request." msgstr "" +#: lib/block_scout_web/templates/page_not_found/index.html.eex:8 +#, elixir-autogen, elixir-format +msgid "This page is no longer explorable! If you are lost, use the search bar to find what you are looking for." +msgstr "" + #: lib/block_scout_web/templates/transaction_state/index.html.eex:17 #, elixir-autogen, elixir-format msgid "This transaction hasn't changed state." @@ -2811,6 +2985,11 @@ msgstr "" msgid "Total Difficulty" msgstr "" +#: lib/block_scout_web/templates/tokens/index.html.eex:43 +#, elixir-autogen, elixir-format +msgid "Total Supply" +msgstr "" + #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:84 #, elixir-autogen, elixir-format msgid "Total Supply * Price" @@ -2864,6 +3043,11 @@ msgstr "" msgid "Transaction %{transaction}, %{subnetwork} %{transaction}" msgstr "" +#: lib/block_scout_web/templates/transaction/overview.html.eex:205 +#, elixir-autogen, elixir-format +msgid "Transaction Action" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:438 #, elixir-autogen, elixir-format msgid "Transaction Burnt Fee" @@ -2892,7 +3076,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:13 #: lib/block_scout_web/templates/account/tag_transaction/index.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:16 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:17 #, elixir-autogen, elixir-format msgid "Transaction Tags" msgstr "" @@ -3064,6 +3248,13 @@ msgstr "" msgid "Validator Name" msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:32 +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:26 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:26 +#, elixir-autogen, elixir-format +msgid "Validator index" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:349 #, elixir-autogen, elixir-format msgid "Value" @@ -3102,6 +3293,11 @@ msgstr "" msgid "Verified contracts - %{subnetwork} Explorer" msgstr "" +#: lib/block_scout_web/templates/verified_contracts/_metatags.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Verified contracts, %{subnetwork}, %{coin}" +msgstr "" + #: lib/block_scout_web/templates/address_contract/index.html.eex:28 #: lib/block_scout_web/templates/address_contract/index.html.eex:30 #: lib/block_scout_web/templates/address_contract/index.html.eex:198 @@ -3194,6 +3390,11 @@ msgstr "" msgid "View the account balance, transactions, and other data for %{address} on the %{network}" msgstr "" +#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:8 +#, elixir-autogen, elixir-format +msgid "View the beacon chain withdrawals on %{subnetwork}" +msgstr "" + #: lib/block_scout_web/templates/block/_metatags.html.eex:10 #, elixir-autogen, elixir-format msgid "View the transactions, token transfers, and uncles for block number %{block_number}" @@ -3243,7 +3444,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:7 #: lib/block_scout_web/templates/account/watchlist/show.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:14 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:15 #, elixir-autogen, elixir-format msgid "Watch list" msgstr "" @@ -3258,6 +3459,15 @@ msgstr "" msgid "Wei" msgstr "" +#: lib/block_scout_web/templates/address/_tabs.html.eex:29 +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:13 +#: lib/block_scout_web/templates/block/_tabs.html.eex:13 +#: lib/block_scout_web/templates/layout/_topnav.html.eex:73 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:5 +#, elixir-autogen, elixir-format +msgid "Withdrawals" +msgstr "" + #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:106 #, elixir-autogen, elixir-format msgid "Write" @@ -3326,6 +3536,11 @@ msgstr "" msgid "Your name*" msgstr "" +#: lib/block_scout_web/templates/error422/index.html.eex:8 +#, elixir-autogen, elixir-format +msgid "Your request contained an error, perhaps a mistyped tx/block/address hash. Try again, and check the developer tools console for more info." +msgstr "" + #: lib/block_scout_web/templates/address/overview.html.eex:111 #, elixir-autogen, elixir-format msgid "at" @@ -3403,6 +3618,11 @@ msgstr "" msgid "of" msgstr "" +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "on sign up. Didn’t receive?" +msgstr "" + #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:16 #, elixir-autogen, elixir-format msgid "page" @@ -3436,202 +3656,3 @@ msgstr "" #, elixir-autogen, elixir-format msgid "truffle flattener" msgstr "" - -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:29 -#, elixir-autogen, elixir-format -msgid "Sign in" -msgstr "" - -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:11 -#, elixir-autogen, elixir-format -msgid "Signed in as " -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:8 -#, elixir-autogen, elixir-format -msgid "1. If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page." -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:9 -#, elixir-autogen, elixir-format -msgid "2. It could still be in the TX Pool of a different node, waiting to be broadcasted." -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:10 -#, elixir-autogen, elixir-format -msgid "3. During times when the network is busy (i.e during ICOs) it can take a while for your transaction to propagate through the network and for us to index it." -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:11 -#, elixir-autogen, elixir-format -msgid "4. If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information." -msgstr "" - -#: lib/block_scout_web/templates/internal_server_error/index.html.eex:8 -#, elixir-autogen, elixir-format -msgid "An unexpected error has occurred. Try reloading the page, or come back soon and try again." -msgstr "" - -#: lib/block_scout_web/templates/error422/index.html.eex:9 -#: lib/block_scout_web/templates/internal_server_error/index.html.eex:9 -#: lib/block_scout_web/templates/page_not_found/index.html.eex:9 -#: lib/block_scout_web/templates/transaction/not_found.html.eex:13 -#, elixir-autogen, elixir-format -msgid "Back to home" -msgstr "" - -#: lib/block_scout_web/templates/internal_server_error/index.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Internal server error" -msgstr "" - -#: lib/block_scout_web/templates/error422/index.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Request cannot be processed" -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:6 -#, elixir-autogen, elixir-format -msgid "Sorry, we are unable to locate this transaction hash" -msgstr "" - -#: lib/block_scout_web/templates/page_not_found/index.html.eex:8 -#, elixir-autogen, elixir-format -msgid "This page is no longer explorable! If you are lost, use the search bar to find what you are looking for." -msgstr "" - -#: lib/block_scout_web/templates/error422/index.html.eex:8 -#, elixir-autogen, elixir-format -msgid "Your request contained an error, perhaps a mistyped tx/block/address hash. Try again, and check the developer tools console for more info." -msgstr "" - -#: lib/block_scout_web/templates/transaction/_actions.html.eex:101 -#, elixir-autogen, elixir-format -msgid "%{qty} of Token ID [%{link_to_id}]" -msgstr "" - -#: lib/block_scout_web/templates/transaction/overview.html.eex:204 -#, elixir-autogen, elixir-format -msgid "Highlighted events of the transaction." -msgstr "" - -#: lib/block_scout_web/templates/transaction/_actions.html.eex:92 -#, elixir-autogen, elixir-format -msgid "Mint of %{address} To %{to}" -msgstr "" - -#: lib/block_scout_web/templates/transaction/overview.html.eex:206 -#, elixir-autogen, elixir-format -msgid "Scroll to see more" -msgstr "" - -#: lib/block_scout_web/templates/transaction/overview.html.eex:205 -#, elixir-autogen, elixir-format -msgid "Transaction Action" -msgstr "" - -#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18 -#, elixir-autogen, elixir-format -msgid "Potential matches from contract method database:" -msgstr "" - -#: lib/block_scout_web/templates/address_contract_verification_common_fields/_yul_contracts_switcher.html.eex:19 -#, elixir-autogen, elixir-format -msgid "Select Yes if you want to verify Yul contract." -msgstr "" - -#: lib/block_scout_web/templates/verified_contracts/_metatags.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Verified contracts, %{subnetwork}, %{coin}" -msgstr "" - -#: lib/block_scout_web/templates/tokens/index.html.eex:38 -#, elixir-autogen, elixir-format -msgid "Circulating Market Cap" -msgstr "" - -#: lib/block_scout_web/templates/tokens/index.html.eex:48 -#, elixir-autogen, elixir-format -msgid "Holders Count" -msgstr "" - -#: lib/block_scout_web/templates/tokens/index.html.eex:43 -#, elixir-autogen, elixir-format -msgid "Total Supply" -msgstr "" - -#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:29 -#, elixir-autogen, elixir-format -msgid "There is no decompiled contracts for this address." -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:38 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:35 -#, elixir-autogen, elixir-format -msgid "Age" -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:41 -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:32 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:38 -#, elixir-autogen, elixir-format -msgid "Amount" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:2 -#, elixir-autogen, elixir-format -msgid "Beacon chain withdrawals - %{subnetwork} Explorer" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Beacon chain, Withdrawals, %{subnetwork}, %{coin}" -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:29 -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:23 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:23 -#, elixir-autogen, elixir-format -msgid "Index" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/index.html.eex:11 -#, elixir-autogen, elixir-format -msgid "There are %{withdrawals_count} withdrawals total that withdrawn %{withdrawals_sum}" -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:54 -#, elixir-autogen, elixir-format -msgid "There are no withdrawals for this address." -msgstr "" - -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:45 -#, elixir-autogen, elixir-format -msgid "There are no withdrawals for this block." -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/index.html.eex:53 -#, elixir-autogen, elixir-format -msgid "There are no withdrawals." -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:32 -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:26 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:26 -#, elixir-autogen, elixir-format -msgid "Validator index" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:8 -#, elixir-autogen, elixir-format -msgid "View the beacon chain withdrawals on %{subnetwork}" -msgstr "" - -#: lib/block_scout_web/templates/address/_tabs.html.eex:29 -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:13 -#: lib/block_scout_web/templates/block/_tabs.html.eex:13 -#: lib/block_scout_web/templates/layout/_topnav.html.eex:73 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:5 -#, elixir-autogen, elixir-format -msgid "Withdrawals" -msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index ea8c96ba25..759f5dd799 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -53,6 +53,11 @@ msgstr "" msgid "%{count} Transactions" msgstr "" +#: lib/block_scout_web/templates/transaction/_actions.html.eex:101 +#, elixir-autogen, elixir-format +msgid "%{qty} of Token ID [%{link_to_id}]" +msgstr "" + #: lib/block_scout_web/templates/chain/_metatags.html.eex:2 #, elixir-autogen, elixir-format msgid "%{subnetwork} %{network} Explorer" @@ -86,6 +91,26 @@ msgstr "" msgid "- We're indexing this chain right now. Some of the counts may be inaccurate." msgstr "" +#: lib/block_scout_web/templates/transaction/not_found.html.eex:8 +#, elixir-autogen, elixir-format +msgid "1. If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page." +msgstr "" + +#: lib/block_scout_web/templates/transaction/not_found.html.eex:9 +#, elixir-autogen, elixir-format +msgid "2. It could still be in the TX Pool of a different node, waiting to be broadcasted." +msgstr "" + +#: lib/block_scout_web/templates/transaction/not_found.html.eex:10 +#, elixir-autogen, elixir-format +msgid "3. During times when the network is busy (i.e during ICOs) it can take a while for your transaction to propagate through the network and for us to index it." +msgstr "" + +#: lib/block_scout_web/templates/transaction/not_found.html.eex:11 +#, elixir-autogen, elixir-format +msgid "4. If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information." +msgstr "" + #: lib/block_scout_web/templates/block/overview.html.eex:195 #, elixir-autogen, elixir-format msgid "64-bit hash of value verifying proof-of-work (note: null for POA chains)." @@ -97,6 +122,11 @@ msgstr "" msgid "A block producer who successfully included the block onto the blockchain." msgstr "" +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "A confirmation email was sent to" +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_common_fields/_library_first.html.eex:4 #, elixir-autogen, elixir-format msgid "A library name called in the .sol file. Multiple libraries (up to " @@ -147,7 +177,7 @@ msgstr "" #: lib/block_scout_web/templates/account/api_key/index.html.eex:7 #: lib/block_scout_web/templates/account/common/_nav.html.eex:16 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:17 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:18 #, elixir-autogen, elixir-format msgid "API keys" msgstr "" @@ -252,7 +282,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:10 #: lib/block_scout_web/templates/account/tag_address/index.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:15 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:16 #, elixir-autogen, elixir-format msgid "Address Tags" msgstr "" @@ -282,6 +312,12 @@ msgstr "" msgid "Addresses" msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:38 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:35 +#, elixir-autogen, elixir-format +msgid "Age" +msgstr "" + #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:26 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28 #: lib/block_scout_web/templates/address_transaction/index.html.eex:22 @@ -310,6 +346,13 @@ msgstr "" msgid "All tokens in the account and total value." msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:41 +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:32 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:38 +#, elixir-autogen, elixir-format +msgid "Amount" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:437 #, elixir-autogen, elixir-format msgid "Amount of" @@ -320,6 +363,11 @@ msgstr "" msgid "Amount of distributed reward. Miners receive a static block reward + Tx fees + uncle fees." msgstr "" +#: lib/block_scout_web/templates/internal_server_error/index.html.eex:8 +#, elixir-autogen, elixir-format +msgid "An unexpected error has occurred. Try reloading the page, or come back soon and try again." +msgstr "" + #: lib/block_scout_web/templates/api_docs/eth_rpc.html.eex:15 #, elixir-autogen, elixir-format msgid "Anything not in this list is not supported. Click on the method to be taken to the documentation for that method, and check the notes section for any potential differences." @@ -365,6 +413,14 @@ msgstr "" msgid "Back to Watch list (Cancel)" msgstr "" +#: lib/block_scout_web/templates/error422/index.html.eex:9 +#: lib/block_scout_web/templates/internal_server_error/index.html.eex:9 +#: lib/block_scout_web/templates/page_not_found/index.html.eex:9 +#: lib/block_scout_web/templates/transaction/not_found.html.eex:13 +#, elixir-autogen, elixir-format +msgid "Back to home" +msgstr "" + #: lib/block_scout_web/templates/account/watchlist/show.html.eex:24 #: lib/block_scout_web/templates/address/overview.html.eex:150 #: lib/block_scout_web/templates/address_token/overview.html.eex:51 @@ -399,6 +455,16 @@ msgstr "" msgid "Base URL:" msgstr "" +#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:2 +#, elixir-autogen, elixir-format +msgid "Beacon chain withdrawals - %{subnetwork} Explorer" +msgstr "" + +#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Beacon chain, Withdrawals, %{subnetwork}, %{coin}" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:472 #, elixir-autogen, elixir-format msgid "Binary data included with the transaction. See input / logs below for additional info." @@ -565,6 +631,11 @@ msgstr "" msgid "Chore Reward" msgstr "" +#: lib/block_scout_web/templates/tokens/index.html.eex:38 +#, elixir-autogen, elixir-format +msgid "Circulating Market Cap" +msgstr "" + #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:137 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:106 #, elixir-autogen, elixir-format @@ -962,7 +1033,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:19 #: lib/block_scout_web/templates/account/custom_abi/form.html.eex:8 #: lib/block_scout_web/templates/account/custom_abi/index.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:18 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:19 #, elixir-autogen, elixir-format msgid "Custom ABI" msgstr "" @@ -1429,11 +1500,21 @@ msgstr "" msgid "Hex (Default)" msgstr "" +#: lib/block_scout_web/templates/transaction/overview.html.eex:204 +#, elixir-autogen, elixir-format +msgid "Highlighted events of the transaction." +msgstr "" + #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:108 #, elixir-autogen, elixir-format msgid "Holders" msgstr "" +#: lib/block_scout_web/templates/tokens/index.html.eex:48 +#, elixir-autogen, elixir-format +msgid "Holders Count" +msgstr "" + #: lib/block_scout_web/templates/api_docs/eth_rpc.html.eex:11 #, elixir-autogen, elixir-format msgid "However, in general, the" @@ -1478,6 +1559,13 @@ msgstr "" msgid "Incoming" msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:29 +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:23 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:23 +#, elixir-autogen, elixir-format +msgid "Index" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:464 #, elixir-autogen, elixir-format msgid "Index position of Transaction in the block." @@ -1518,6 +1606,11 @@ msgstr "" msgid "Internal Transactions" msgstr "" +#: lib/block_scout_web/templates/internal_server_error/index.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Internal server error" +msgstr "" + #: lib/block_scout_web/templates/tokens/inventory/index.html.eex:16 #: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:19 #: lib/block_scout_web/views/tokens/overview_view.ex:42 @@ -1709,6 +1802,11 @@ msgstr "" msgid "Minimum fee required per unit of gas. Fee adjusts based on network congestion." msgstr "" +#: lib/block_scout_web/templates/transaction/_actions.html.eex:92 +#, elixir-autogen, elixir-format +msgid "Mint of %{address} To %{to}" +msgstr "" + #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:223 #, elixir-autogen, elixir-format msgid "Model" @@ -1984,6 +2082,12 @@ msgstr "" msgid "Play" msgstr "" +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:22 +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "Please confirm your email address to use the My Account feature." +msgstr "" + #: lib/block_scout_web/templates/account/watchlist_address/form.html.eex:68 #, elixir-autogen, elixir-format msgid "Please select notification methods:" @@ -2004,6 +2108,11 @@ msgstr "" msgid "Position %{index}" msgstr "" +#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18 +#, elixir-autogen, elixir-format +msgid "Potential matches from contract method database:" +msgstr "" + #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:32 #, elixir-autogen, elixir-format msgid "Potential matches from our contract method database:" @@ -2043,12 +2152,12 @@ msgid "Priority Fees" msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:4 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:13 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:14 #, elixir-autogen, elixir-format msgid "Profile" msgstr "" -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:19 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:20 #, elixir-autogen, elixir-format msgid "Public Tags" msgstr "" @@ -2139,6 +2248,11 @@ msgstr "" msgid "Request a public tag/label" msgstr "" +#: lib/block_scout_web/templates/error422/index.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Request cannot be processed" +msgstr "" + #: lib/block_scout_web/templates/account/public_tags_request/index.html.eex:37 #, elixir-autogen, elixir-format msgid "Request to add public tag" @@ -2149,6 +2263,11 @@ msgstr "" msgid "Request to edit a public tag/label" msgstr "" +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "Resend verification email" +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:112 #: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:38 #: lib/block_scout_web/templates/address_contract_verification_via_multi_part_files/new.html.eex:104 @@ -2201,6 +2320,11 @@ msgstr "" msgid "Save" msgstr "" +#: lib/block_scout_web/templates/transaction/overview.html.eex:206 +#, elixir-autogen, elixir-format +msgid "Scroll to see more" +msgstr "" + #: lib/block_scout_web/templates/address_logs/index.html.eex:16 #: lib/block_scout_web/templates/layout/_search.html.eex:34 #, elixir-autogen, elixir-format @@ -2222,6 +2346,11 @@ msgstr "" msgid "Search tokens" msgstr "" +#: lib/block_scout_web/templates/address_contract_verification_common_fields/_yul_contracts_switcher.html.eex:19 +#, elixir-autogen, elixir-format +msgid "Select Yes if you want to verify Yul contract." +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_common_fields/_include_nightly_builds_field.html.eex:19 #, elixir-autogen, elixir-format msgid "Select yes if you want to show nightly builds." @@ -2273,11 +2402,21 @@ msgstr "" msgid "Shows total assets held in the address" msgstr "" -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:20 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:33 +#, elixir-autogen, elixir-format +msgid "Sign in" +msgstr "" + +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:24 #, elixir-autogen, elixir-format msgid "Sign out" msgstr "" +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:11 +#, elixir-autogen, elixir-format +msgid "Signed in as " +msgstr "" + #: lib/block_scout_web/templates/block/overview.html.eex:114 #, elixir-autogen, elixir-format msgid "Size" @@ -2344,6 +2483,11 @@ msgstr "" msgid "Something went wrong, click to retry." msgstr "" +#: lib/block_scout_web/templates/transaction/not_found.html.eex:6 +#, elixir-autogen, elixir-format +msgid "Sorry, we are unable to locate this transaction hash" +msgstr "" + #: lib/block_scout_web/templates/address_contract_verification_via_multi_part_files/new.html.eex:63 #, elixir-autogen, elixir-format msgid "Sources *.sol files" @@ -2500,6 +2644,11 @@ msgstr "" msgid "The total gas amount used in the block and its percentage of gas filled in the block." msgstr "" +#: lib/block_scout_web/templates/withdrawal/index.html.eex:11 +#, elixir-autogen, elixir-format +msgid "There are %{withdrawals_count} withdrawals total that withdrawn %{withdrawals_sum}" +msgstr "" + #: lib/block_scout_web/templates/address_validation/index.html.eex:16 #, elixir-autogen, elixir-format msgid "There are no blocks validated by this address." @@ -2587,11 +2736,31 @@ msgstr "" msgid "There are no verified contracts." msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:54 +#, elixir-autogen, elixir-format +msgid "There are no withdrawals for this address." +msgstr "" + +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:45 +#, elixir-autogen, elixir-format +msgid "There are no withdrawals for this block." +msgstr "" + +#: lib/block_scout_web/templates/withdrawal/index.html.eex:53 +#, elixir-autogen, elixir-format +msgid "There are no withdrawals." +msgstr "" + #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:35 #, elixir-autogen, elixir-format msgid "There is no coin history for this address." msgstr "" +#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:29 +#, elixir-autogen, elixir-format +msgid "There is no decompiled contracts for this address." +msgstr "" + #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:21 #: lib/block_scout_web/templates/chain/show.html.eex:9 #, elixir-autogen, elixir-format @@ -2628,6 +2797,11 @@ msgstr "" msgid "This is useful to allow sending requests to blockscout without having to change anything about the request." msgstr "" +#: lib/block_scout_web/templates/page_not_found/index.html.eex:8 +#, elixir-autogen, elixir-format +msgid "This page is no longer explorable! If you are lost, use the search bar to find what you are looking for." +msgstr "" + #: lib/block_scout_web/templates/transaction_state/index.html.eex:17 #, elixir-autogen, elixir-format msgid "This transaction hasn't changed state." @@ -2811,6 +2985,11 @@ msgstr "" msgid "Total Difficulty" msgstr "" +#: lib/block_scout_web/templates/tokens/index.html.eex:43 +#, elixir-autogen, elixir-format +msgid "Total Supply" +msgstr "" + #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:84 #, elixir-autogen, elixir-format msgid "Total Supply * Price" @@ -2864,6 +3043,11 @@ msgstr "" msgid "Transaction %{transaction}, %{subnetwork} %{transaction}" msgstr "" +#: lib/block_scout_web/templates/transaction/overview.html.eex:205 +#, elixir-autogen, elixir-format +msgid "Transaction Action" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:438 #, elixir-autogen, elixir-format msgid "Transaction Burnt Fee" @@ -2892,7 +3076,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:13 #: lib/block_scout_web/templates/account/tag_transaction/index.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:16 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:17 #, elixir-autogen, elixir-format msgid "Transaction Tags" msgstr "" @@ -3064,6 +3248,13 @@ msgstr "" msgid "Validator Name" msgstr "" +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:32 +#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:26 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:26 +#, elixir-autogen, elixir-format +msgid "Validator index" +msgstr "" + #: lib/block_scout_web/templates/transaction/overview.html.eex:349 #, elixir-autogen, elixir-format msgid "Value" @@ -3102,6 +3293,11 @@ msgstr "" msgid "Verified contracts - %{subnetwork} Explorer" msgstr "" +#: lib/block_scout_web/templates/verified_contracts/_metatags.html.eex:7 +#, elixir-autogen, elixir-format +msgid "Verified contracts, %{subnetwork}, %{coin}" +msgstr "" + #: lib/block_scout_web/templates/address_contract/index.html.eex:28 #: lib/block_scout_web/templates/address_contract/index.html.eex:30 #: lib/block_scout_web/templates/address_contract/index.html.eex:198 @@ -3194,6 +3390,11 @@ msgstr "" msgid "View the account balance, transactions, and other data for %{address} on the %{network}" msgstr "" +#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:8 +#, elixir-autogen, elixir-format +msgid "View the beacon chain withdrawals on %{subnetwork}" +msgstr "" + #: lib/block_scout_web/templates/block/_metatags.html.eex:10 #, elixir-autogen, elixir-format msgid "View the transactions, token transfers, and uncles for block number %{block_number}" @@ -3243,7 +3444,7 @@ msgstr "" #: lib/block_scout_web/templates/account/common/_nav.html.eex:7 #: lib/block_scout_web/templates/account/watchlist/show.html.eex:7 -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:14 +#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:15 #, elixir-autogen, elixir-format msgid "Watch list" msgstr "" @@ -3258,6 +3459,15 @@ msgstr "" msgid "Wei" msgstr "" +#: lib/block_scout_web/templates/address/_tabs.html.eex:29 +#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:13 +#: lib/block_scout_web/templates/block/_tabs.html.eex:13 +#: lib/block_scout_web/templates/layout/_topnav.html.eex:73 +#: lib/block_scout_web/templates/withdrawal/index.html.eex:5 +#, elixir-autogen, elixir-format +msgid "Withdrawals" +msgstr "" + #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:106 #, elixir-autogen, elixir-format msgid "Write" @@ -3326,6 +3536,11 @@ msgstr "" msgid "Your name*" msgstr "" +#: lib/block_scout_web/templates/error422/index.html.eex:8 +#, elixir-autogen, elixir-format +msgid "Your request contained an error, perhaps a mistyped tx/block/address hash. Try again, and check the developer tools console for more info." +msgstr "" + #: lib/block_scout_web/templates/address/overview.html.eex:111 #, elixir-autogen, elixir-format msgid "at" @@ -3403,6 +3618,11 @@ msgstr "" msgid "of" msgstr "" +#: lib/block_scout_web/templates/layout/app.html.eex:97 +#, elixir-autogen, elixir-format +msgid "on sign up. Didn’t receive?" +msgstr "" + #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:16 #, elixir-autogen, elixir-format msgid "page" @@ -3436,202 +3656,3 @@ msgstr "" #, elixir-autogen, elixir-format msgid "truffle flattener" msgstr "" - -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:29 -#, elixir-autogen, elixir-format -msgid "Sign in" -msgstr "" - -#: lib/block_scout_web/templates/layout/_account_menu_item.html.eex:11 -#, elixir-autogen, elixir-format -msgid "Signed in as " -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:8 -#, elixir-autogen, elixir-format, fuzzy -msgid "1. If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page." -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:9 -#, elixir-autogen, elixir-format, fuzzy -msgid "2. It could still be in the TX Pool of a different node, waiting to be broadcasted." -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:10 -#, elixir-autogen, elixir-format, fuzzy -msgid "3. During times when the network is busy (i.e during ICOs) it can take a while for your transaction to propagate through the network and for us to index it." -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:11 -#, elixir-autogen, elixir-format, fuzzy -msgid "4. If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information." -msgstr "" - -#: lib/block_scout_web/templates/internal_server_error/index.html.eex:8 -#, elixir-autogen, elixir-format -msgid "An unexpected error has occurred. Try reloading the page, or come back soon and try again." -msgstr "" - -#: lib/block_scout_web/templates/error422/index.html.eex:9 -#: lib/block_scout_web/templates/internal_server_error/index.html.eex:9 -#: lib/block_scout_web/templates/page_not_found/index.html.eex:9 -#: lib/block_scout_web/templates/transaction/not_found.html.eex:13 -#, elixir-autogen, elixir-format, fuzzy -msgid "Back to home" -msgstr "" - -#: lib/block_scout_web/templates/internal_server_error/index.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Internal server error" -msgstr "" - -#: lib/block_scout_web/templates/error422/index.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Request cannot be processed" -msgstr "" - -#: lib/block_scout_web/templates/transaction/not_found.html.eex:6 -#, elixir-autogen, elixir-format, fuzzy -msgid "Sorry, we are unable to locate this transaction hash" -msgstr "" - -#: lib/block_scout_web/templates/page_not_found/index.html.eex:8 -#, elixir-autogen, elixir-format -msgid "This page is no longer explorable! If you are lost, use the search bar to find what you are looking for." -msgstr "" - -#: lib/block_scout_web/templates/error422/index.html.eex:8 -#, elixir-autogen, elixir-format -msgid "Your request contained an error, perhaps a mistyped tx/block/address hash. Try again, and check the developer tools console for more info." -msgstr "" - -#: lib/block_scout_web/templates/transaction/_actions.html.eex:101 -#, elixir-autogen, elixir-format -msgid "%{qty} of Token ID [%{link_to_id}]" -msgstr "" - -#: lib/block_scout_web/templates/transaction/overview.html.eex:204 -#, elixir-autogen, elixir-format -msgid "Highlighted events of the transaction." -msgstr "" - -#: lib/block_scout_web/templates/transaction/_actions.html.eex:92 -#, elixir-autogen, elixir-format -msgid "Mint of %{address} To %{to}" -msgstr "" - -#: lib/block_scout_web/templates/transaction/overview.html.eex:206 -#, elixir-autogen, elixir-format -msgid "Scroll to see more" -msgstr "" - -#: lib/block_scout_web/templates/transaction/overview.html.eex:205 -#, elixir-autogen, elixir-format, fuzzy -msgid "Transaction Action" -msgstr "" - -#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18 -#, elixir-autogen, elixir-format, fuzzy -msgid "Potential matches from contract method database:" -msgstr "" - -#: lib/block_scout_web/templates/address_contract_verification_common_fields/_yul_contracts_switcher.html.eex:19 -#, elixir-autogen, elixir-format, fuzzy -msgid "Select Yes if you want to verify Yul contract." -msgstr "" - -#: lib/block_scout_web/templates/verified_contracts/_metatags.html.eex:7 -#, elixir-autogen, elixir-format, fuzzy -msgid "Verified contracts, %{subnetwork}, %{coin}" -msgstr "" - -#: lib/block_scout_web/templates/tokens/index.html.eex:38 -#, elixir-autogen, elixir-format -msgid "Circulating Market Cap" -msgstr "" - -#: lib/block_scout_web/templates/tokens/index.html.eex:48 -#, elixir-autogen, elixir-format, fuzzy -msgid "Holders Count" -msgstr "" - -#: lib/block_scout_web/templates/tokens/index.html.eex:43 -#, elixir-autogen, elixir-format, fuzzy -msgid "Total Supply" -msgstr "" - -#: lib/block_scout_web/templates/address_decompiled_contract/index.html.eex:29 -#, elixir-autogen, elixir-format -msgid "There is no decompiled contracts for this address." -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:38 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:35 -#, elixir-autogen, elixir-format -msgid "Age" -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:41 -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:32 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:38 -#, elixir-autogen, elixir-format, fuzzy -msgid "Amount" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:2 -#, elixir-autogen, elixir-format -msgid "Beacon chain withdrawals - %{subnetwork} Explorer" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:7 -#, elixir-autogen, elixir-format -msgid "Beacon chain, Withdrawals, %{subnetwork}, %{coin}" -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:29 -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:23 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:23 -#, elixir-autogen, elixir-format, fuzzy -msgid "Index" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/index.html.eex:11 -#, elixir-autogen, elixir-format -msgid "There are %{withdrawals_count} withdrawals total that withdrawn %{withdrawals_sum}" -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:54 -#, elixir-autogen, elixir-format, fuzzy -msgid "There are no withdrawals for this address." -msgstr "" - -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:45 -#, elixir-autogen, elixir-format, fuzzy -msgid "There are no withdrawals for this block." -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/index.html.eex:53 -#, elixir-autogen, elixir-format, fuzzy -msgid "There are no withdrawals." -msgstr "" - -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:32 -#: lib/block_scout_web/templates/block_withdrawal/index.html.eex:26 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:26 -#, elixir-autogen, elixir-format, fuzzy -msgid "Validator index" -msgstr "" - -#: lib/block_scout_web/templates/withdrawal/_metatags.html.eex:8 -#, elixir-autogen, elixir-format, fuzzy -msgid "View the beacon chain withdrawals on %{subnetwork}" -msgstr "" - -#: lib/block_scout_web/templates/address/_tabs.html.eex:29 -#: lib/block_scout_web/templates/address_withdrawal/index.html.eex:13 -#: lib/block_scout_web/templates/block/_tabs.html.eex:13 -#: lib/block_scout_web/templates/layout/_topnav.html.eex:73 -#: lib/block_scout_web/templates/withdrawal/index.html.eex:5 -#, elixir-autogen, elixir-format -msgid "Withdrawals" -msgstr "" diff --git a/apps/explorer/lib/explorer/account/identity.ex b/apps/explorer/lib/explorer/account/identity.ex index d0766d7d35..05171bc9f7 100644 --- a/apps/explorer/lib/explorer/account/identity.ex +++ b/apps/explorer/lib/explorer/account/identity.ex @@ -17,6 +17,7 @@ defmodule Explorer.Account.Identity do field(:name, Explorer.Encrypted.Binary) field(:nickname, Explorer.Encrypted.Binary) field(:avatar, Explorer.Encrypted.Binary) + field(:verification_email_sent_at, :utc_datetime_usec) has_many(:tag_addresses, TagAddress) has_many(:watchlists, Watchlist) @@ -29,7 +30,7 @@ defmodule Explorer.Account.Identity do @doc false def changeset(identity, attrs) do identity - |> cast(attrs, [:uid, :email, :name, :nickname, :avatar]) + |> cast(attrs, [:uid, :email, :name, :nickname, :avatar, :verification_email_sent_at]) |> validate_required([:uid, :email, :name]) |> put_hashed_fields() end diff --git a/apps/explorer/lib/explorer/third_party_integrations/auth0.ex b/apps/explorer/lib/explorer/third_party_integrations/auth0.ex new file mode 100644 index 0000000000..4afad8845f --- /dev/null +++ b/apps/explorer/lib/explorer/third_party_integrations/auth0.ex @@ -0,0 +1,48 @@ +defmodule Explorer.ThirdPartyIntegrations.Auth0 do + @moduledoc """ + Module for fetching jwt auth0 Management API (https://auth0.com/docs/api/management/v2) jwt + """ + @redis_key "auth0" + + @doc """ + Function responsible for retrieving machine to machine JWT for interacting with Auth0 Management API. + Firstly it tries to access cached token and if there is no cached one, token will be requested from Auth0 + """ + @spec get_m2m_jwt() :: nil | String.t() + def get_m2m_jwt, do: get_m2m_jwt_inner(Redix.command(:redix, ["GET", @redis_key])) + + def get_m2m_jwt_inner({:ok, token}) when not is_nil(token), do: token + + def get_m2m_jwt_inner(_) do + config = Application.get_env(:ueberauth, Ueberauth.Strategy.Auth0.OAuth) + + body = %{ + "client_id" => config[:client_id], + "client_secret" => config[:client_secret], + "audience" => "https://#{config[:domain]}/api/v2/", + "grant_type" => "client_credentials" + } + + headers = [{"Content-type", "application/json"}] + + case HTTPoison.post("https://#{config[:domain]}/oauth/token", Jason.encode!(body), headers, []) do + {:ok, %HTTPoison.Response{status_code: 200, body: body}} -> + case Jason.decode!(body) do + %{"access_token" => token, "expires_in" => ttl} -> + cache_token(token, ttl - 1) + + _ -> + nil + end + + _ -> + nil + end + end + + defp cache_token(token, ttl) do + chain_id = Application.get_env(:block_scout_web, :chain_id) + Redix.command(:redix, ["SET", "#{chain_id}_#{@redis_key}", token, "EX", ttl]) + token + end +end diff --git a/apps/explorer/priv/account/migrations/20230502083519_add_verification_email_sent_at.exs b/apps/explorer/priv/account/migrations/20230502083519_add_verification_email_sent_at.exs new file mode 100644 index 0000000000..a3145bab49 --- /dev/null +++ b/apps/explorer/priv/account/migrations/20230502083519_add_verification_email_sent_at.exs @@ -0,0 +1,9 @@ +defmodule Explorer.Repo.Account.Migrations.AddVerificationEmailSentAt do + use Ecto.Migration + + def change do + alter table(:account_identities) do + add(:verification_email_sent_at, :"timestamp without time zone", null: true) + end + end +end diff --git a/config/runtime.exs b/config/runtime.exs index 216e45857f..b949b4b410 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -356,7 +356,8 @@ config :explorer, Explorer.Account, sendgrid: [ sender: System.get_env("ACCOUNT_SENDGRID_SENDER"), template: System.get_env("ACCOUNT_SENDGRID_TEMPLATE") - ] + ], + resend_interval: ConfigHelper.parse_time_env_var("ACCOUNT_VERIFICATION_EMAIL_RESEND_INTERVAL", "5m") config :explorer, :token_id_migration, first_block: ConfigHelper.parse_integer_env_var("TOKEN_ID_MIGRATION_FIRST_BLOCK", 0), diff --git a/docker-compose/envs/common-blockscout.env b/docker-compose/envs/common-blockscout.env index bd23653152..eeba9bbf77 100644 --- a/docker-compose/envs/common-blockscout.env +++ b/docker-compose/envs/common-blockscout.env @@ -201,3 +201,4 @@ ACCOUNT_REDIS_URL=redis://redis_db:6379 # AMPLITUDE_URL= EIP_1559_ELASTICITY_MULTIPLIER=2 # API_SENSITIVE_ENDPOINTS_KEY= +# ACCOUNT_VERIFICATION_EMAIL_RESEND_INTERVAL= diff --git a/docker/Makefile b/docker/Makefile index b10f12ebfe..2b1826af45 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -701,6 +701,9 @@ endif ifdef API_SENSITIVE_ENDPOINTS_KEY BLOCKSCOUT_CONTAINER_PARAMS += -e 'API_SENSITIVE_ENDPOINTS_KEY=$(API_SENSITIVE_ENDPOINTS_KEY)' endif +ifdef ACCOUNT_VERIFICATION_EMAIL_RESEND_INTERVAL + BLOCKSCOUT_CONTAINER_PARAMS += -e 'ACCOUNT_VERIFICATION_EMAIL_RESEND_INTERVAL=$(ACCOUNT_VERIFICATION_EMAIL_RESEND_INTERVAL)' +endif HAS_BLOCKSCOUT_IMAGE := $(shell docker images | grep -sw "${BS_CONTAINER_IMAGE} ") build: