diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml
index 8eb84c5df6..c87ed7e041 100644
--- a/.github/workflows/config.yml
+++ b/.github/workflows/config.yml
@@ -4,6 +4,7 @@ on:
push:
branches:
- account
+ - np-separate-account-separate-db
env:
MIX_ENV: test
@@ -37,7 +38,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-
@@ -97,7 +98,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -121,7 +122,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -144,7 +145,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_13-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -184,7 +185,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -210,7 +211,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -238,7 +239,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -284,7 +285,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -343,7 +344,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -399,7 +400,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -466,7 +467,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -527,7 +528,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_12-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_14-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
diff --git a/.gitignore b/.gitignore
index a069fb5fd6..2f86dc1f3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,9 @@
/*.ez
/logs
+# mix dialyzer artifacts
+/priv/plts
+
# Generated on crash by the VM
erl_crash.dump
diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs
index 2787d53282..f6e44d7013 100644
--- a/apps/block_scout_web/config/config.exs
+++ b/apps/block_scout_web/config/config.exs
@@ -8,7 +8,7 @@ import Config
# General application configuration
config :block_scout_web,
namespace: BlockScoutWeb,
- ecto_repos: [Explorer.Repo]
+ ecto_repos: [Explorer.Repo, Explorer.Repo.Account]
config :block_scout_web,
admin_panel_enabled: System.get_env("ADMIN_PANEL_ENABLED", "") == "true"
@@ -97,7 +97,7 @@ config :hammer,
config :block_scout_web, BlockScoutWeb.Guardian, issuer: "block_scout_web"
config :guardian, Guardian.DB,
- repo: Explorer.Repo,
+ repo: Explorer.Repo.Account,
schema_name: "guardian_tokens",
sweep_interval: 60
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 9f11f75e6d..529de91d5b 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,8 @@ defmodule BlockScoutWeb.Account.Api.V1.TagsController do
uid = Plug.current_claims(conn)["sub"]
with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)},
- {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.preload(identity, :watchlists)},
+ {:watchlist, %{watchlists: [watchlist | _]}} <-
+ {:watchlist, Repo.account_repo().preload(identity, :watchlists)},
{:address_hash, {:ok, address_hash}} <- {:address_hash, Address.cast(address_hash)} do
GetAddressTags.get_address_tags(address_hash, %{id: identity.id, watchlist_id: watchlist.id})
else
@@ -57,7 +58,8 @@ defmodule BlockScoutWeb.Account.Api.V1.TagsController do
uid = Plug.current_claims(conn)["sub"]
with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)},
- {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.preload(identity, :watchlists)},
+ {:watchlist, %{watchlists: [watchlist | _]}} <-
+ {:watchlist, Repo.account_repo().preload(identity, :watchlists)},
false <- is_nil(transaction) do
GetTransactionTags.get_transaction_with_addresses_tags(transaction, %{
id: identity.id,
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 63e14cb789..6b3e9098ea 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
@@ -30,11 +30,9 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do
uid = Plug.current_claims(conn)["sub"]
with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)},
- {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.preload(identity, :watchlists)},
- watchlist_with_addresses <-
- Repo.preload(watchlist,
- watchlist_addresses: {from(wa in WatchlistAddress, order_by: [desc: wa.id]), [:address]}
- ) do
+ {:watchlist, %{watchlists: [watchlist | _]}} <-
+ {:watchlist, Repo.account_repo().preload(identity, :watchlists)},
+ watchlist_with_addresses <- preload_watchlist_address_fetched_coin_balance(watchlist) do
conn
|> put_status(200)
|> render(:watchlist_addresses, %{
@@ -48,7 +46,8 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do
uid = Plug.current_claims(conn)["sub"]
with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)},
- {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.preload(identity, :watchlists)},
+ {:watchlist, %{watchlists: [watchlist | _]}} <-
+ {:watchlist, Repo.account_repo().preload(identity, :watchlists)},
{count, _} <- WatchlistAddress.delete(watchlist_address_id, watchlist.id),
{:watchlist_delete, true} <- {:watchlist_delete, count > 0} do
conn
@@ -100,10 +99,11 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do
}
with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)},
- {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.preload(identity, :watchlists)},
+ {:watchlist, %{watchlists: [watchlist | _]}} <-
+ {:watchlist, Repo.account_repo().preload(identity, :watchlists)},
{:ok, watchlist_address} <-
WatchlistAddress.create(Map.put(watchlist_params, :watchlist_id, watchlist.id)),
- watchlist_address_preloaded <- Repo.preload(watchlist_address, :address) do
+ watchlist_address_preloaded <- WatchlistAddress.preload_address_fetched_coin_balance(watchlist_address) do
conn
|> put_status(200)
|> render(:watchlist_address, %{
@@ -158,10 +158,11 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do
}
with {:identity, [%Identity{} = identity]} <- {:identity, UserFromAuth.find_identity(uid)},
- {:watchlist, %{watchlists: [watchlist | _]}} <- {:watchlist, Repo.preload(identity, :watchlists)},
+ {:watchlist, %{watchlists: [watchlist | _]}} <-
+ {:watchlist, Repo.account_repo().preload(identity, :watchlists)},
{:ok, watchlist_address} <-
WatchlistAddress.update(Map.put(watchlist_params, :watchlist_id, watchlist.id)),
- watchlist_address_preloaded <- Repo.preload(watchlist_address, :address) do
+ watchlist_address_preloaded <- WatchlistAddress.preload_address_fetched_coin_balance(watchlist_address) do
conn
|> put_status(200)
|> render(:watchlist_address, %{
@@ -482,4 +483,10 @@ defmodule BlockScoutWeb.Account.Api.V1.UserController do
defp reject_nil_map_values(map) when is_map(map) do
Map.reject(map, fn {_k, v} -> is_nil(v) end)
end
+
+ defp preload_watchlist_address_fetched_coin_balance(watchlist) do
+ watchlist
+ |> Repo.account_repo().preload(watchlist_addresses: from(wa in WatchlistAddress, order_by: [desc: wa.id]))
+ |> WatchlistAddress.preload_address_fetched_coin_balance()
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/account/watchlist_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/account/watchlist_controller.ex
index b774d57c44..f8c548322f 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/account/watchlist_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/account/watchlist_controller.ex
@@ -19,7 +19,8 @@ defmodule BlockScoutWeb.Account.WatchlistController do
defp watchlist_with_addresses(user) do
Watchlist
- |> Repo.get(user.watchlist_id)
- |> Repo.preload(watchlist_addresses: {from(wa in WatchlistAddress, order_by: [desc: wa.id]), [:address]})
+ |> Repo.account_repo().get(user.watchlist_id)
+ |> Repo.account_repo().preload(watchlist_addresses: from(wa in WatchlistAddress, order_by: [desc: wa.id]))
+ |> WatchlistAddress.preload_address_fetched_coin_balance()
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/models/get_address_tags.ex b/apps/block_scout_web/lib/block_scout_web/models/get_address_tags.ex
index ea4b5b32da..4a834f3fef 100644
--- a/apps/block_scout_web/lib/block_scout_web/models/get_address_tags.ex
+++ b/apps/block_scout_web/lib/block_scout_web/models/get_address_tags.ex
@@ -54,7 +54,7 @@ defmodule BlockScoutWeb.Models.GetAddressTags do
select: %{label: ta.name, display_name: ta.name, address_hash: ta.address_hash}
)
- Repo.all(query)
+ Repo.account_repo().all(query)
end
def get_personal_tags(_, _), do: []
@@ -68,7 +68,7 @@ defmodule BlockScoutWeb.Models.GetAddressTags do
select: %{label: wa.name, display_name: wa.name}
)
- Repo.all(query)
+ Repo.account_repo().all(query)
end
def get_watchlist_names_on_address(_, _), do: []
diff --git a/apps/block_scout_web/lib/block_scout_web/models/get_transaction_tags.ex b/apps/block_scout_web/lib/block_scout_web/models/get_transaction_tags.ex
index 776622c2b4..bee4eb9354 100644
--- a/apps/block_scout_web/lib/block_scout_web/models/get_transaction_tags.ex
+++ b/apps/block_scout_web/lib/block_scout_web/models/get_transaction_tags.ex
@@ -21,7 +21,7 @@ defmodule BlockScoutWeb.Models.GetTransactionTags do
def get_transaction_with_addresses_tags(_, _), do: %{personal_tags: [], watchlist_names: [], personal_tx_tag: nil}
def get_transaction_tags(transaction_hash, %{id: identity_id}) do
- Repo.get_by(TagTransaction, tx_hash: transaction_hash, identity_id: identity_id)
+ Repo.account_repo().get_by(TagTransaction, tx_hash: transaction_hash, identity_id: identity_id)
end
def get_transaction_tags(_, _), do: nil
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 fe45d6fbf0..cc1483b929 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
@@ -37,7 +37,7 @@ defmodule BlockScoutWeb.Models.UserFromAuth do
end
defp create_identity(auth) do
- with {:ok, %Identity{} = identity} <- Repo.insert(new_identity(auth)),
+ with {:ok, %Identity{} = identity} <- Repo.account_repo().insert(new_identity(auth)),
{:ok, _watchlist} <- add_watchlist(identity) do
identity
end
@@ -46,7 +46,7 @@ defmodule BlockScoutWeb.Models.UserFromAuth do
defp update_identity(identity, attrs) do
identity
|> Identity.changeset(attrs)
- |> Repo.update()
+ |> Repo.account_repo().update()
end
defp new_identity(auth) do
@@ -62,12 +62,12 @@ defmodule BlockScoutWeb.Models.UserFromAuth do
defp add_watchlist(identity) do
watchlist = Ecto.build_assoc(identity, :watchlists, %{})
- with {:ok, _} <- Repo.insert(watchlist),
+ with {:ok, _} <- Repo.account_repo().insert(watchlist),
do: {:ok, identity}
end
def find_identity(auth_or_uid) do
- Repo.all(query_identity(auth_or_uid))
+ Repo.account_repo().all(query_identity(auth_or_uid))
end
def query_identity(%Auth{} = auth) do
@@ -79,7 +79,7 @@ defmodule BlockScoutWeb.Models.UserFromAuth do
end
defp basic_info(auth, identity) do
- %{watchlists: [watchlist | _]} = Repo.preload(identity, :watchlists)
+ %{watchlists: [watchlist | _]} = Repo.account_repo().preload(identity, :watchlists)
%{
id: identity.id,
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/account/watchlist_address/row.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/account/watchlist_address/row.html.eex
index b8fa97dd5b..467c15952f 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/account/watchlist_address/row.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/account/watchlist_address/row.html.eex
@@ -8,12 +8,12 @@
- <%= balance_ether(@watchlist_address.address) %>
+ <%= balance_ether(@watchlist_address.fetched_coin_balance) %>
( watchlist.id,
"address_hash" => watchlist.address_hash,
"name" => watchlist.name,
- "address_balance" => if(watchlist.address.fetched_coin_balance, do: watchlist.address.fetched_coin_balance.value),
+ "address_balance" => if(watchlist.fetched_coin_balance, do: watchlist.fetched_coin_balance.value),
"exchange_rate" => exchange_rate.usd_value,
"notification_settings" => %{
"native" => %{
diff --git a/apps/block_scout_web/lib/block_scout_web/views/account/watchlist_address_view.ex b/apps/block_scout_web/lib/block_scout_web/views/account/watchlist_address_view.ex
index 0605862572..f3f538399e 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/account/watchlist_address_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/account/watchlist_address_view.ex
@@ -3,11 +3,9 @@ defmodule BlockScoutWeb.Account.WatchlistAddressView do
import BlockScoutWeb.AddressView, only: [trimmed_hash: 1]
import BlockScoutWeb.WeiHelpers, only: [format_wei_value: 2]
- alias Explorer.Chain.Address
+ def balance_ether(nil), do: ""
- def balance_ether(%Address{fetched_coin_balance: nil}), do: ""
-
- def balance_ether(%Address{fetched_coin_balance: balance}) do
+ def balance_ether(balance) do
format_wei_value(balance, :ether)
end
end
diff --git a/apps/block_scout_web/test/block_scout_web/models/user_from_auth_test.exs b/apps/block_scout_web/test/block_scout_web/models/user_from_auth_test.exs
index d1d99501a3..2d13f11600 100644
--- a/apps/block_scout_web/test/block_scout_web/models/user_from_auth_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/models/user_from_auth_test.exs
@@ -37,13 +37,13 @@ defmodule UserFromAuthTest do
email: "john@blockscout.com",
name: "John Snow",
uid: "github|666666"
- } = Identity |> first |> Repo.one()
+ } = Identity |> first |> Repo.account_repo().one()
%{
id: watchlist_id,
identity_id: ^identity_id,
name: "default"
- } = Watchlist |> first |> Repo.one()
+ } = Watchlist |> first |> Repo.account_repo().one()
assert {:ok,
%{
@@ -84,13 +84,13 @@ defmodule UserFromAuthTest do
email: "john@blockscout.com",
name: "John Snow",
uid: "google-oauth2|666666"
- } = Identity |> first |> Repo.one()
+ } = Identity |> first |> Repo.account_repo().one()
%{
id: watchlist_id,
identity_id: ^identity_id,
name: "default"
- } = Watchlist |> first |> Repo.one()
+ } = Watchlist |> first |> Repo.account_repo().one()
assert {:ok,
%{
diff --git a/apps/block_scout_web/test/support/conn_case.ex b/apps/block_scout_web/test/support/conn_case.ex
index 787709ccb7..5ae6216f0c 100644
--- a/apps/block_scout_web/test/support/conn_case.ex
+++ b/apps/block_scout_web/test/support/conn_case.ex
@@ -37,9 +37,11 @@ defmodule BlockScoutWeb.ConnCase do
@dialyzer {:nowarn_function, __ex_unit_setup_0: 1}
setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo)
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo.Account)
unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()})
+ Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo.Account, {:shared, self()})
end
Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id())
diff --git a/apps/block_scout_web/test/test_helper.exs b/apps/block_scout_web/test/test_helper.exs
index 9aeb6c8fa7..11c846c47c 100644
--- a/apps/block_scout_web/test/test_helper.exs
+++ b/apps/block_scout_web/test/test_helper.exs
@@ -25,6 +25,7 @@ ExUnit.start()
Mox.defmock(Explorer.ExchangeRates.Source.TestSource, for: Explorer.ExchangeRates.Source)
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, :manual)
+Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo.Account, :manual)
Absinthe.Test.prime(BlockScoutWeb.Schema)
diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs
index cc58587a54..c58d3bfd37 100644
--- a/apps/explorer/config/config.exs
+++ b/apps/explorer/config/config.exs
@@ -7,7 +7,7 @@ import Config
# General application configuration
config :explorer,
- ecto_repos: [Explorer.Repo],
+ ecto_repos: [Explorer.Repo, Explorer.Repo.Account],
token_functions_reader_max_retries: 3
config :explorer, Explorer.Counters.AverageBlockTime,
diff --git a/apps/explorer/config/dev.exs b/apps/explorer/config/dev.exs
index 7d7bd024a7..1ccfb34b6d 100644
--- a/apps/explorer/config/dev.exs
+++ b/apps/explorer/config/dev.exs
@@ -6,6 +6,9 @@ config :explorer, Explorer.Repo, timeout: :timer.seconds(80)
# Configure API database
config :explorer, Explorer.Repo.Replica1, timeout: :timer.seconds(80)
+# Configure Account database
+config :explorer, Explorer.Repo.Account, timeout: :timer.seconds(80)
+
config :explorer, Explorer.Tracer, env: "dev", disabled?: true
config :logger, :explorer,
diff --git a/apps/explorer/config/prod.exs b/apps/explorer/config/prod.exs
index 8b42271e33..2d389e59d6 100644
--- a/apps/explorer/config/prod.exs
+++ b/apps/explorer/config/prod.exs
@@ -10,6 +10,11 @@ config :explorer, Explorer.Repo.Replica1,
prepare: :unnamed,
timeout: :timer.seconds(60)
+# Configures Account database
+config :explorer, Explorer.Repo.Account,
+ prepare: :unnamed,
+ timeout: :timer.seconds(60)
+
config :explorer, Explorer.Tracer, env: "production", disabled?: true
config :logger, :explorer,
diff --git a/apps/explorer/config/test.exs b/apps/explorer/config/test.exs
index 3c7fc40fec..1b3b160791 100644
--- a/apps/explorer/config/test.exs
+++ b/apps/explorer/config/test.exs
@@ -23,6 +23,16 @@ config :explorer, Explorer.Repo.Replica1,
timeout: :timer.seconds(60),
queue_target: 1000
+# Configure API database
+config :explorer, Explorer.Repo.Account,
+ database: "explorer_test_account",
+ hostname: "localhost",
+ pool: Ecto.Adapters.SQL.Sandbox,
+ # Default of `5_000` was too low for `BlockFetcher` test
+ ownership_timeout: :timer.minutes(1),
+ timeout: :timer.seconds(60),
+ queue_target: 1000
+
config :logger, :explorer,
level: :warn,
path: Path.absname("logs/test/explorer.log")
diff --git a/apps/explorer/lib/explorer/account/api/key.ex b/apps/explorer/lib/explorer/account/api/key.ex
index ef24979034..ab80d41ec2 100644
--- a/apps/explorer/lib/explorer/account/api/key.ex
+++ b/apps/explorer/lib/explorer/account/api/key.ex
@@ -41,14 +41,14 @@ defmodule Explorer.Account.Api.Key do
def create(attrs) do
%__MODULE__{}
|> changeset(Map.put(attrs, :value, generate_api_key()))
- |> Repo.insert()
+ |> Repo.account_repo().insert()
end
def api_key_count_constraint(%Changeset{changes: %{identity_id: identity_id}} = api_key) do
if identity_id
|> api_keys_by_identity_id_query()
|> limit(@max_key_per_account)
- |> Repo.aggregate(:count, :value) >= @max_key_per_account do
+ |> Repo.account_repo().aggregate(:count, :value) >= @max_key_per_account do
api_key
|> add_error(:name, "Max #{@max_key_per_account} keys per account")
else
@@ -81,7 +81,7 @@ defmodule Explorer.Account.Api.Key do
def get_api_key_by_value_and_identity_id(value, identity_id) when not is_nil(value) and not is_nil(identity_id) do
value
|> api_key_by_value_and_identity_id_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_api_key_by_value_and_identity_id(_, _), do: nil
@@ -89,7 +89,7 @@ defmodule Explorer.Account.Api.Key do
def update(%{value: api_key_value, identity_id: identity_id} = attrs) do
with api_key <- get_api_key_by_value_and_identity_id(api_key_value, identity_id),
false <- is_nil(api_key) do
- api_key |> changeset(attrs) |> Repo.update()
+ api_key |> changeset(attrs) |> Repo.account_repo().update()
else
true ->
{:error, %{reason: :item_not_found}}
@@ -99,7 +99,7 @@ defmodule Explorer.Account.Api.Key do
def delete(api_key_value, identity_id) when not is_nil(api_key_value) and not is_nil(identity_id) do
api_key_value
|> api_key_by_value_and_identity_id_query(identity_id)
- |> Repo.delete_all()
+ |> Repo.account_repo().delete_all()
end
def delete(_, _), do: nil
@@ -107,7 +107,7 @@ defmodule Explorer.Account.Api.Key do
def get_api_keys_by_identity_id(id) when not is_nil(id) do
id
|> api_keys_by_identity_id_query()
- |> Repo.all()
+ |> Repo.account_repo().all()
end
def get_api_keys_by_identity_id(_), do: nil
@@ -116,8 +116,8 @@ defmodule Explorer.Account.Api.Key do
if match?({:ok, _casted_api_key}, UUID.cast(api_key_value)) do
__MODULE__
|> where([api_key], api_key.value == ^api_key_value)
- |> Repo.one()
- |> Repo.preload(identity: :plan)
+ |> Repo.account_repo().one()
+ |> Repo.account_repo().preload(identity: :plan)
else
nil
end
diff --git a/apps/explorer/lib/explorer/account/custom_abi.ex b/apps/explorer/lib/explorer/account/custom_abi.ex
index e18e809ae3..4be56dd007 100644
--- a/apps/explorer/lib/explorer/account/custom_abi.ex
+++ b/apps/explorer/lib/explorer/account/custom_abi.ex
@@ -8,7 +8,7 @@ defmodule Explorer.Account.CustomABI do
alias Ecto.Changeset
alias Explorer.Account.Identity
alias Explorer.{Chain, Repo}
- alias Explorer.Chain.{Address, Hash}
+ alias Explorer.Chain.Hash
import Ecto.Changeset
@@ -19,8 +19,9 @@ defmodule Explorer.Account.CustomABI do
field(:abi, {:array, :map})
field(:given_abi, :string, virtual: true)
field(:abi_validating_error, :string, virtual: true)
+ field(:address_hash, Hash.Address, null: false)
+
belongs_to(:identity, Identity)
- belongs_to(:address, Address, foreign_key: :address_hash, references: :hash, type: Hash.Address)
timestamps()
end
@@ -34,7 +35,6 @@ defmodule Explorer.Account.CustomABI do
|> validate_custom_abi()
|> check_smart_contract_address()
|> foreign_key_constraint(:identity_id, message: "User not found")
- |> foreign_key_constraint(:address_hash, message: "Address not found")
|> unique_constraint([:identity_id, :address_hash],
message: "Custom ABI for this address has already been added before"
)
@@ -48,23 +48,23 @@ defmodule Explorer.Account.CustomABI do
end
defp check_smart_contract_address(%Changeset{changes: %{address_hash: address_hash}} = custom_abi) do
- if Chain.is_address_hash_is_smart_contract?(address_hash) do
- custom_abi
- else
- add_error(custom_abi, :address_hash, "Address is not a smart contract")
- end
+ check_smart_contract_address_inner(custom_abi, address_hash)
end
defp check_smart_contract_address(%Changeset{data: %{address_hash: address_hash}} = custom_abi) do
+ check_smart_contract_address_inner(custom_abi, address_hash)
+ end
+
+ defp check_smart_contract_address(custom_abi), do: custom_abi
+
+ defp check_smart_contract_address_inner(changeset, address_hash) do
if Chain.is_address_hash_is_smart_contract?(address_hash) do
- custom_abi
+ changeset
else
- add_error(custom_abi, :address_hash, "Address is not a smart contract")
+ add_error(changeset, :address_hash, "Address is not a smart contract")
end
end
- defp check_smart_contract_address(custom_abi), do: custom_abi
-
defp validate_custom_abi(%Changeset{changes: %{given_abi: given_abi, abi_validating_error: error}} = custom_abi) do
custom_abi
|> add_error(:abi, error)
@@ -130,7 +130,7 @@ defmodule Explorer.Account.CustomABI do
if identity_id
|> custom_abis_by_identity_id_query()
|> limit(@max_abis_per_account)
- |> Repo.aggregate(:count, :id) >= @max_abis_per_account do
+ |> Repo.account_repo().aggregate(:count, :id) >= @max_abis_per_account do
add_error(custom_abi, :name, "Max #{@max_abis_per_account} ABIs per account")
else
custom_abi
@@ -142,7 +142,7 @@ defmodule Explorer.Account.CustomABI do
def create(attrs) do
%__MODULE__{}
|> changeset(attrs)
- |> Repo.insert()
+ |> Repo.account_repo().insert()
end
def custom_abis_by_identity_id_query(id) when not is_nil(id) do
@@ -173,7 +173,7 @@ defmodule Explorer.Account.CustomABI do
when not is_nil(identity_id) and not is_nil(address_hash) do
address_hash
|> custom_abi_by_identity_id_and_address_hash_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_custom_abi_by_identity_id_and_address_hash(_, _), do: nil
@@ -181,7 +181,7 @@ defmodule Explorer.Account.CustomABI do
def get_custom_abi_by_id_and_identity_id(id, identity_id) when not is_nil(id) and not is_nil(identity_id) do
id
|> custom_abi_by_id_and_identity_id_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_custom_abi_by_id_and_identity_id(_, _), do: nil
@@ -189,7 +189,7 @@ defmodule Explorer.Account.CustomABI do
def get_custom_abis_by_identity_id(id) when not is_nil(id) do
id
|> custom_abis_by_identity_id_query()
- |> Repo.all()
+ |> Repo.account_repo().all()
end
def get_custom_abis_by_identity_id(_), do: nil
@@ -197,7 +197,7 @@ defmodule Explorer.Account.CustomABI do
def delete(id, identity_id) when not is_nil(id) and not is_nil(identity_id) do
id
|> custom_abi_by_id_and_identity_id_query(identity_id)
- |> Repo.delete_all()
+ |> Repo.account_repo().delete_all()
end
def delete(_, _), do: nil
@@ -207,7 +207,7 @@ defmodule Explorer.Account.CustomABI do
false <- is_nil(custom_abi) do
custom_abi
|> changeset(attrs)
- |> Repo.update()
+ |> Repo.account_repo().update()
else
true ->
{:error, %{reason: :item_not_found}}
diff --git a/apps/explorer/lib/explorer/account/identity.ex b/apps/explorer/lib/explorer/account/identity.ex
index 3c39533459..49e75cc6a0 100644
--- a/apps/explorer/lib/explorer/account/identity.ex
+++ b/apps/explorer/lib/explorer/account/identity.ex
@@ -16,8 +16,10 @@ defmodule Explorer.Account.Identity do
field(:name, :string)
field(:nickname, :string)
field(:avatar, :string)
+
has_many(:tag_addresses, TagAddress)
has_many(:watchlists, Watchlist)
+
belongs_to(:plan, Plan)
timestamps()
diff --git a/apps/explorer/lib/explorer/account/notifier/email.ex b/apps/explorer/lib/explorer/account/notifier/email.ex
index 03d4f51b94..35555e3169 100644
--- a/apps/explorer/lib/explorer/account/notifier/email.ex
+++ b/apps/explorer/lib/explorer/account/notifier/email.ex
@@ -85,9 +85,9 @@ defmodule Explorer.Account.Notifier.Email do
do: name
defp address_hash_string(%WatchlistNotification{
- watchlist_address: %WatchlistAddress{address: address}
+ watchlist_address: %WatchlistAddress{address_hash: address_hash}
}),
- do: hash_string(address.hash)
+ do: hash_string(address_hash)
defp hash_string(hash) do
"0x" <> Base.encode16(hash.bytes, case: :lower)
@@ -114,7 +114,7 @@ defmodule Explorer.Account.Notifier.Email do
end
defp preload(notification) do
- Repo.preload(notification, watchlist_address: [:address, watchlist: :identity])
+ Repo.account_repo().preload(notification, watchlist_address: [watchlist: :identity])
end
defp address_url(address_hash) do
diff --git a/apps/explorer/lib/explorer/account/notifier/notify.ex b/apps/explorer/lib/explorer/account/notifier/notify.ex
index 86a37ea346..b935442baa 100644
--- a/apps/explorer/lib/explorer/account/notifier/notify.ex
+++ b/apps/explorer/lib/explorer/account/notifier/notify.ex
@@ -64,7 +64,7 @@ defmodule Explorer.Account.Notifier.Notify do
) do
notification
|> query_notification(address)
- |> Repo.all()
+ |> Repo.account_repo().all()
|> case do
[] -> save_and_send_notification(notification, address)
_ -> :ok
@@ -91,7 +91,7 @@ defmodule Explorer.Account.Notifier.Notify do
end
defp save_and_send_notification(%WatchlistNotification{} = notification, %WatchlistAddress{} = address) do
- Repo.insert(notification)
+ Repo.account_repo().insert(notification)
email = Email.compose(notification, address)
@@ -143,6 +143,6 @@ defmodule Explorer.Account.Notifier.Notify do
defp find_watchlists_addresses(%Explorer.Chain.Hash{} = address_hash) do
query = from(wa in WatchlistAddress, where: wa.address_hash == ^address_hash)
- Repo.all(query)
+ Repo.account_repo().all(query)
end
end
diff --git a/apps/explorer/lib/explorer/account/public_tags_request.ex b/apps/explorer/lib/explorer/account/public_tags_request.ex
index d62881b2ff..273d7b5b18 100644
--- a/apps/explorer/lib/explorer/account/public_tags_request.ex
+++ b/apps/explorer/lib/explorer/account/public_tags_request.ex
@@ -75,7 +75,7 @@ defmodule Explorer.Account.PublicTagsRequest do
def create(attrs) do
%__MODULE__{}
|> changeset(Map.put(attrs, :request_type, "add"))
- |> Repo.insert()
+ |> Repo.account_repo().insert()
|> AirTable.submit()
end
@@ -90,7 +90,7 @@ defmodule Explorer.Account.PublicTagsRequest do
if identity_id
|> public_tags_requests_by_identity_id_query()
|> limit(@max_public_tags_request_per_account)
- |> Repo.aggregate(:count, :id) >= @max_public_tags_request_per_account do
+ |> Repo.account_repo().aggregate(:count, :id) >= @max_public_tags_request_per_account do
request
|> add_error(:tags, "Max #{@max_public_tags_request_per_account} public tags requests per account")
else
@@ -113,7 +113,7 @@ defmodule Explorer.Account.PublicTagsRequest do
fragment("? && ?", public_tags_request.addresses, ^Enum.map(prepared_addresses, fn x -> x.bytes end))
)
|> limit(1)
- |> Repo.one()
+ |> Repo.account_repo().one()
now = DateTime.utc_now()
@@ -192,7 +192,7 @@ defmodule Explorer.Account.PublicTagsRequest do
def public_tags_request_by_id_and_identity_id_query(_, _), do: nil
def get_public_tags_request_by_id_and_identity_id(id, identity_id) when not is_nil(id) and not is_nil(identity_id) do
- id |> public_tags_request_by_id_and_identity_id_query(identity_id) |> Repo.one()
+ id |> public_tags_request_by_id_and_identity_id_query(identity_id) |> Repo.account_repo().one()
end
def get_public_tags_request_by_id_and_identity_id(_, _), do: nil
@@ -200,7 +200,7 @@ defmodule Explorer.Account.PublicTagsRequest do
def get_public_tags_requests_by_identity_id(id) when not is_nil(id) do
id
|> public_tags_requests_by_identity_id_query()
- |> Repo.all()
+ |> Repo.account_repo().all()
end
def get_public_tags_requests_by_identity_id(_), do: nil
@@ -208,7 +208,7 @@ defmodule Explorer.Account.PublicTagsRequest do
def delete_public_tags_request(identity_id, id) when not is_nil(id) and not is_nil(identity_id) do
id
|> public_tags_request_by_id_and_identity_id_query(identity_id)
- |> Repo.delete_all()
+ |> Repo.account_repo().delete_all()
end
def delete_public_tags_request(_, _), do: nil
@@ -216,7 +216,8 @@ defmodule Explorer.Account.PublicTagsRequest do
def update(%{id: id, identity_id: identity_id} = attrs) do
with public_tags_request <- get_public_tags_request_by_id_and_identity_id(id, identity_id),
false <- is_nil(public_tags_request),
- {:ok, changeset} <- public_tags_request |> changeset(Map.put(attrs, :request_type, "edit")) |> Repo.update() do
+ {:ok, changeset} <-
+ public_tags_request |> changeset(Map.put(attrs, :request_type, "edit")) |> Repo.account_repo().update() do
AirTable.submit({:ok, changeset})
else
true ->
@@ -233,7 +234,7 @@ defmodule Explorer.Account.PublicTagsRequest do
{:ok, changeset} <-
public_tags_request
|> changeset_without_constraints(%{request_type: "delete", remove_reason: remove_reason})
- |> Repo.update() do
+ |> Repo.account_repo().update() do
case AirTable.submit({:ok, changeset}) do
{:error, changeset} ->
changeset
diff --git a/apps/explorer/lib/explorer/account/tag_address.ex b/apps/explorer/lib/explorer/account/tag_address.ex
index 6a3bd89c2b..49c2bcb63f 100644
--- a/apps/explorer/lib/explorer/account/tag_address.ex
+++ b/apps/explorer/lib/explorer/account/tag_address.ex
@@ -16,14 +16,9 @@ defmodule Explorer.Account.TagAddress do
schema "account_tag_addresses" do
field(:name, :string)
+ field(:address_hash, Hash.Address, null: false)
belongs_to(:identity, Identity)
- belongs_to(:address, Address,
- foreign_key: :address_hash,
- references: :hash,
- type: Hash.Address
- )
-
timestamps()
end
@@ -42,30 +37,37 @@ defmodule Explorer.Account.TagAddress do
|> validate_length(:name, min: 1, max: 35)
|> unique_constraint([:identity_id, :address_hash], message: "Address tag already exists")
|> check_existance_or_create_address()
- |> foreign_key_constraint(:address_hash, message: "")
|> tag_address_count_constraint()
end
def create(attrs) do
%__MODULE__{}
|> changeset(attrs)
- |> Repo.insert()
+ |> Repo.account_repo().insert()
end
defp check_existance_or_create_address(%Changeset{changes: %{address_hash: address_hash}, valid?: true} = changeset) do
+ check_existance_or_create_address_inner(changeset, address_hash)
+ end
+
+ defp check_existance_or_create_address(%Changeset{data: %{address_hash: address_hash}, valid?: true} = changeset) do
+ check_existance_or_create_address_inner(changeset, address_hash)
+ end
+
+ defp check_existance_or_create_address(changeset), do: changeset
+
+ defp check_existance_or_create_address_inner(changeset, address_hash) do
with {:ok, hash} <- Hash.Address.cast(address_hash),
{:ok, %Address{}} <- Chain.find_or_insert_address_from_hash(hash, []) do
changeset
end
end
- defp check_existance_or_create_address(changeset), do: changeset
-
def tag_address_count_constraint(%Changeset{changes: %{identity_id: identity_id}} = tag_address) do
if identity_id
|> tags_address_by_identity_id_query()
|> limit(@max_tag_address_per_account)
- |> Repo.aggregate(:count, :id) >= @max_tag_address_per_account do
+ |> Repo.account_repo().aggregate(:count, :id) >= @max_tag_address_per_account do
tag_address
|> add_error(:name, "Max #{@max_tag_address_per_account} tags per account")
else
@@ -86,7 +88,7 @@ defmodule Explorer.Account.TagAddress do
def get_tags_address_by_identity_id(id) when not is_nil(id) do
id
|> tags_address_by_identity_id_query()
- |> Repo.all()
+ |> Repo.account_repo().all()
end
def get_tags_address_by_identity_id(_), do: nil
@@ -103,7 +105,7 @@ defmodule Explorer.Account.TagAddress do
when not is_nil(address_hash) and not is_nil(identity_id) do
address_hash
|> tag_address_by_address_hash_and_identity_id_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_tag_address_by_address_hash_and_identity_id(_, _), do: nil
@@ -120,7 +122,7 @@ defmodule Explorer.Account.TagAddress do
when not is_nil(tag_id) and not is_nil(identity_id) do
tag_id
|> tag_address_by_id_and_identity_id_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_tag_address_by_id_and_identity_id_query(_, _), do: nil
@@ -128,7 +130,7 @@ defmodule Explorer.Account.TagAddress do
def delete(tag_id, identity_id) when not is_nil(tag_id) and not is_nil(identity_id) do
tag_id
|> tag_address_by_id_and_identity_id_query(identity_id)
- |> Repo.delete_all()
+ |> Repo.account_repo().delete_all()
end
def delete(_, _), do: nil
@@ -136,7 +138,7 @@ defmodule Explorer.Account.TagAddress do
def update(%{id: tag_id, identity_id: identity_id} = attrs) do
with tag <- get_tag_address_by_id_and_identity_id_query(tag_id, identity_id),
false <- is_nil(tag) do
- tag |> changeset(attrs) |> Repo.update()
+ tag |> changeset(attrs) |> Repo.account_repo().update()
else
true ->
{:error, %{reason: :item_not_found}}
diff --git a/apps/explorer/lib/explorer/account/tag_transaction.ex b/apps/explorer/lib/explorer/account/tag_transaction.ex
index b8d6d40538..4a2a87c160 100644
--- a/apps/explorer/lib/explorer/account/tag_transaction.ex
+++ b/apps/explorer/lib/explorer/account/tag_transaction.ex
@@ -9,20 +9,16 @@ defmodule Explorer.Account.TagTransaction do
alias Ecto.Changeset
alias Explorer.Account.Identity
- alias Explorer.Chain.{Hash, Transaction}
- alias Explorer.Repo
+ alias Explorer.{Chain, Repo}
+ alias Explorer.Chain.Hash
@max_tag_transaction_per_account 15
schema "account_tag_transactions" do
field(:name, :string)
- belongs_to(:identity, Identity)
+ field(:tx_hash, Hash.Full, null: false)
- belongs_to(:transaction, Transaction,
- foreign_key: :tx_hash,
- references: :hash,
- type: Hash.Full
- )
+ belongs_to(:identity, Identity)
timestamps()
end
@@ -41,21 +37,37 @@ defmodule Explorer.Account.TagTransaction do
|> validate_required(@attrs, message: "Required")
|> validate_length(:name, min: 1, max: 35)
|> unique_constraint([:identity_id, :tx_hash], message: "Transaction tag already exists")
- |> foreign_key_constraint(:tx_hash, message: "Transaction does not exist")
|> tag_transaction_count_constraint()
+ |> check_transaction_existance()
end
def create(attrs) do
%__MODULE__{}
|> changeset(attrs)
- |> Repo.insert()
+ |> Repo.account_repo().insert()
+ end
+
+ defp check_transaction_existance(%Changeset{changes: %{tx_hash: tx_hash}} = changeset) do
+ check_transaction_existance_inner(changeset, tx_hash)
+ end
+
+ defp check_transaction_existance(%Changeset{data: %{tx_hash: tx_hash}} = changeset) do
+ check_transaction_existance_inner(changeset, tx_hash)
+ end
+
+ defp check_transaction_existance_inner(changeset, tx_hash) do
+ if match?({:ok, _}, Chain.hash_to_transaction(tx_hash)) do
+ changeset
+ else
+ add_error(changeset, :tx_hash, "Transaction does not exist")
+ end
end
def tag_transaction_count_constraint(%Changeset{changes: %{identity_id: identity_id}} = tag_transaction) do
if identity_id
|> tags_transaction_by_identity_id_query()
|> limit(@max_tag_transaction_per_account)
- |> Repo.aggregate(:count, :id) >= @max_tag_transaction_per_account do
+ |> Repo.account_repo().aggregate(:count, :id) >= @max_tag_transaction_per_account do
tag_transaction
|> add_error(:name, "Max #{@max_tag_transaction_per_account} tags per account")
else
@@ -76,7 +88,7 @@ defmodule Explorer.Account.TagTransaction do
def get_tags_transaction_by_identity_id(id) when not is_nil(id) do
id
|> tags_transaction_by_identity_id_query()
- |> Repo.all()
+ |> Repo.account_repo().all()
end
def get_tags_transaction_by_identity_id(_), do: nil
@@ -93,7 +105,7 @@ defmodule Explorer.Account.TagTransaction do
when not is_nil(address_hash) and not is_nil(identity_id) do
address_hash
|> tag_transaction_by_address_hash_and_identity_id_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_tag_transaction_by_address_hash_and_identity_id(_, _), do: nil
@@ -110,7 +122,7 @@ defmodule Explorer.Account.TagTransaction do
when not is_nil(tag_id) and not is_nil(identity_id) do
tag_id
|> tag_transaction_by_id_and_identity_id_query(identity_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_tag_transaction_by_id_and_identity_id_query(_, _), do: nil
@@ -118,7 +130,7 @@ defmodule Explorer.Account.TagTransaction do
def delete(tag_id, identity_id) when not is_nil(tag_id) and not is_nil(identity_id) do
tag_id
|> tag_transaction_by_id_and_identity_id_query(identity_id)
- |> Repo.delete_all()
+ |> Repo.account_repo().delete_all()
end
def delete(_, _), do: nil
@@ -126,7 +138,7 @@ defmodule Explorer.Account.TagTransaction do
def update(%{id: tag_id, identity_id: identity_id} = attrs) do
with tag <- get_tag_transaction_by_id_and_identity_id_query(tag_id, identity_id),
false <- is_nil(tag) do
- tag |> changeset(attrs) |> Repo.update()
+ tag |> changeset(attrs) |> Repo.account_repo().update()
else
true ->
{:error, %{reason: :item_not_found}}
diff --git a/apps/explorer/lib/explorer/account/watchlist.ex b/apps/explorer/lib/explorer/account/watchlist.ex
index 8fe02ae43a..cd6998b83f 100644
--- a/apps/explorer/lib/explorer/account/watchlist.ex
+++ b/apps/explorer/lib/explorer/account/watchlist.ex
@@ -14,7 +14,6 @@ defmodule Explorer.Account.Watchlist do
field(:name, :string)
belongs_to(:identity, Identity)
has_many(:watchlist_addresses, WatchlistAddress)
- has_many(:addresses, through: [:watchlist_addresses, :address])
timestamps()
end
diff --git a/apps/explorer/lib/explorer/account/watchlist_address.ex b/apps/explorer/lib/explorer/account/watchlist_address.ex
index 65abb8b69e..e65084a4f9 100644
--- a/apps/explorer/lib/explorer/account/watchlist_address.ex
+++ b/apps/explorer/lib/explorer/account/watchlist_address.ex
@@ -11,13 +11,14 @@ defmodule Explorer.Account.WatchlistAddress do
alias Explorer.Account.Notifier.ForbiddenAddress
alias Explorer.Account.Watchlist
alias Explorer.{Chain, Repo}
- alias Explorer.Chain.{Address, Hash}
+ alias Explorer.Chain.{Address, Hash, Wei}
@max_watchlist_addresses_per_account 10
schema "account_watchlist_addresses" do
field(:name, :string)
- belongs_to(:address, Address, foreign_key: :address_hash, references: :hash, type: Hash.Address)
+ field(:address_hash, Hash.Address, null: false)
+
belongs_to(:watchlist, Watchlist)
field(:watch_coin_input, :boolean, default: true)
@@ -33,6 +34,8 @@ defmodule Explorer.Account.WatchlistAddress do
field(:notify_feed, :boolean)
field(:notify_inapp, :boolean)
+ field(:fetched_coin_balance, Wei, virtual: true)
+
timestamps()
end
@@ -51,21 +54,20 @@ defmodule Explorer.Account.WatchlistAddress do
|> validate_required([:name, :address_hash, :watchlist_id], message: "Required")
|> unique_constraint([:watchlist_id, :address_hash], message: "Address already added to the watch list")
|> check_address()
- |> foreign_key_constraint(:address_hash, message: "")
|> watchlist_address_count_constraint()
end
def create(attrs) do
%__MODULE__{}
|> changeset(attrs)
- |> Repo.insert()
+ |> Repo.account_repo().insert()
end
def watchlist_address_count_constraint(%Changeset{changes: %{watchlist_id: watchlist_id}} = watchlist_address) do
if watchlist_id
|> watchlist_addresses_by_watchlist_id_query()
|> limit(@max_watchlist_addresses_per_account)
- |> Repo.aggregate(:count, :id) >= @max_watchlist_addresses_per_account do
+ |> Repo.account_repo().aggregate(:count, :id) >= @max_watchlist_addresses_per_account do
watchlist_address
|> add_error(:name, "Max #{@max_watchlist_addresses_per_account} watch list addresses per account")
else
@@ -76,6 +78,16 @@ defmodule Explorer.Account.WatchlistAddress do
def watchlist_address_count_constraint(changeset), do: changeset
defp check_address(%Changeset{changes: %{address_hash: address_hash}, valid?: true} = changeset) do
+ check_address_inner(changeset, address_hash)
+ end
+
+ defp check_address(%Changeset{data: %{address_hash: address_hash}, valid?: true} = changeset) do
+ check_address_inner(changeset, address_hash)
+ end
+
+ defp check_address(changeset), do: changeset
+
+ defp check_address_inner(changeset, address_hash) do
with {:ok, address_hash} <- ForbiddenAddress.check(address_hash),
{:ok, %Address{}} <- Chain.find_or_insert_address_from_hash(address_hash, []) do
changeset
@@ -88,8 +100,6 @@ defmodule Explorer.Account.WatchlistAddress do
end
end
- defp check_address(changeset), do: changeset
-
def watchlist_addresses_by_watchlist_id_query(watchlist_id) when not is_nil(watchlist_id) do
__MODULE__
|> where([wl_address], wl_address.watchlist_id == ^watchlist_id)
@@ -109,7 +119,7 @@ defmodule Explorer.Account.WatchlistAddress do
when not is_nil(watchlist_address_id) and not is_nil(watchlist_id) do
watchlist_address_id
|> watchlist_address_by_id_and_watchlist_id_query(watchlist_id)
- |> Repo.one()
+ |> Repo.account_repo().one()
end
def get_watchlist_address_by_id_and_watchlist_id(_, _), do: nil
@@ -118,7 +128,7 @@ defmodule Explorer.Account.WatchlistAddress do
when not is_nil(watchlist_address_id) and not is_nil(watchlist_id) do
watchlist_address_id
|> watchlist_address_by_id_and_watchlist_id_query(watchlist_id)
- |> Repo.delete_all()
+ |> Repo.account_repo().delete_all()
end
def delete(_, _), do: nil
@@ -128,7 +138,7 @@ defmodule Explorer.Account.WatchlistAddress do
false <- is_nil(watchlist_address) do
watchlist_address
|> changeset(attrs)
- |> Repo.update()
+ |> Repo.account_repo().update()
else
true ->
{:error, %{reason: :item_not_found}}
@@ -136,4 +146,19 @@ defmodule Explorer.Account.WatchlistAddress do
end
def get_max_watchlist_addresses_count, do: @max_watchlist_addresses_per_account
+
+ def preload_address_fetched_coin_balance(%Watchlist{watchlist_addresses: watchlist_addresses} = watchlist) do
+ w_addresses =
+ Enum.map(watchlist_addresses, fn wa ->
+ preload_address_fetched_coin_balance(wa)
+ end)
+
+ %Watchlist{watchlist | watchlist_addresses: w_addresses}
+ end
+
+ def preload_address_fetched_coin_balance(%__MODULE__{address_hash: address_hash} = watchlist_address) do
+ %__MODULE__{watchlist_address | fetched_coin_balance: address_hash |> Address.fetched_coin_balance() |> Repo.one()}
+ end
+
+ def preload_address_fetched_coin_balance(watchlist), do: watchlist
end
diff --git a/apps/explorer/lib/explorer/account/watchlist_notification.ex b/apps/explorer/lib/explorer/account/watchlist_notification.ex
index a5731a4f2a..7de98721db 100644
--- a/apps/explorer/lib/explorer/account/watchlist_notification.ex
+++ b/apps/explorer/lib/explorer/account/watchlist_notification.ex
@@ -9,12 +9,7 @@ defmodule Explorer.Account.WatchlistNotification do
import Ecto.Changeset
alias Explorer.Account.WatchlistAddress
-
- alias Explorer.Chain.{
- Address,
- Hash,
- Transaction
- }
+ alias Explorer.Chain.Hash
schema "account_watchlist_notifications" do
field(:amount, :decimal)
@@ -29,27 +24,9 @@ defmodule Explorer.Account.WatchlistNotification do
belongs_to(:watchlist_address, WatchlistAddress)
- belongs_to(
- :from_address,
- Address,
- foreign_key: :from_address_hash,
- references: :hash,
- type: Hash.Address
- )
-
- belongs_to(
- :to_address,
- Address,
- foreign_key: :to_address_hash,
- references: :hash,
- type: Hash.Address
- )
-
- belongs_to(:transaction, Transaction,
- foreign_key: :transaction_hash,
- references: :hash,
- type: Hash.Full
- )
+ field(:from_address_hash, Hash.Address)
+ field(:to_address_hash, Hash.Address)
+ field(:transaction_hash, Hash.Full)
timestamps()
end
diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex
index c42370c0e5..eea99e8573 100644
--- a/apps/explorer/lib/explorer/application.ex
+++ b/apps/explorer/lib/explorer/application.ex
@@ -43,6 +43,7 @@ defmodule Explorer.Application do
base_children = [
Explorer.Repo,
Explorer.Repo.Replica1,
+ Explorer.Repo.Account,
Supervisor.child_spec({SpandexDatadog.ApiServer, datadog_opts()}, id: SpandexDatadog.ApiServer),
Supervisor.child_spec({Task.Supervisor, name: Explorer.HistoryTaskSupervisor}, id: Explorer.HistoryTaskSupervisor),
Supervisor.child_spec({Task.Supervisor, name: Explorer.MarketTaskSupervisor}, id: Explorer.MarketTaskSupervisor),
diff --git a/apps/explorer/lib/explorer/chain/address.ex b/apps/explorer/lib/explorer/chain/address.ex
index 1a71d3e224..163dd66f8d 100644
--- a/apps/explorer/lib/explorer/chain/address.ex
+++ b/apps/explorer/lib/explorer/chain/address.ex
@@ -259,6 +259,12 @@ defmodule Explorer.Chain.Address do
)
end
+ def fetched_coin_balance(address_hash) when not is_nil(address_hash) do
+ Address
+ |> where([address], address.hash == ^address_hash)
+ |> select([address], address.fetched_coin_balance)
+ end
+
defimpl String.Chars do
@doc """
Uses `hash` as string representation, formatting it according to the eip-55 specification
diff --git a/apps/explorer/lib/explorer/repo.ex b/apps/explorer/lib/explorer/repo.ex
index 14a48d9d33..c64db8b97d 100644
--- a/apps/explorer/lib/explorer/repo.ex
+++ b/apps/explorer/lib/explorer/repo.ex
@@ -128,10 +128,54 @@ defmodule Explorer.Repo do
def replica, do: Explorer.Repo.Replica1
end
+ def account_repo, do: Explorer.Repo.Account
+
defmodule Replica1 do
use Ecto.Repo,
otp_app: :explorer,
adapter: Ecto.Adapters.Postgres,
read_only: true
+
+ def init(_, opts) do
+ db_url = Application.get_env(:explorer, Explorer.Repo.Replica1)[:url]
+ repo_conf = Application.get_env(:explorer, Explorer.Repo.Replica1)
+
+ merged =
+ %{url: db_url}
+ |> ConfigHelper.get_db_config()
+ |> Keyword.merge(repo_conf, fn
+ _key, v1, nil -> v1
+ _key, nil, v2 -> v2
+ _, _, v2 -> v2
+ end)
+
+ Application.put_env(:explorer, Explorer.Repo.Replica1, merged)
+
+ {:ok, Keyword.put(opts, :url, db_url)}
+ end
+ end
+
+ defmodule Account do
+ use Ecto.Repo,
+ otp_app: :explorer,
+ adapter: Ecto.Adapters.Postgres
+
+ def init(_, opts) do
+ db_url = Application.get_env(:explorer, Explorer.Repo.Account)[:url]
+ repo_conf = Application.get_env(:explorer, Explorer.Repo.Account)
+
+ merged =
+ %{url: db_url}
+ |> ConfigHelper.get_db_config()
+ |> Keyword.merge(repo_conf, fn
+ _key, v1, nil -> v1
+ _key, nil, v2 -> v2
+ _, _, v2 -> v2
+ end)
+
+ Application.put_env(:explorer, Explorer.Repo.Account, merged)
+
+ {:ok, Keyword.put(opts, :url, db_url)}
+ end
end
end
diff --git a/apps/explorer/lib/explorer/third_party_integrations/airtable.ex b/apps/explorer/lib/explorer/third_party_integrations/airtable.ex
index 93137f3bc7..cd7e1e0f88 100644
--- a/apps/explorer/lib/explorer/third_party_integrations/airtable.ex
+++ b/apps/explorer/lib/explorer/third_party_integrations/airtable.ex
@@ -12,7 +12,7 @@ defmodule Explorer.ThirdPartyIntegrations.AirTable do
if Mix.env() == :test do
new_request
|> PublicTagsRequest.changeset(%{request_id: "123"})
- |> Repo.update()
+ |> Repo.account_repo().update()
input
else
@@ -33,7 +33,7 @@ defmodule Explorer.ThirdPartyIntegrations.AirTable do
new_request
|> PublicTagsRequest.changeset(%{request_id: request_id})
- |> Repo.update()
+ |> Repo.account_repo().update()
input
diff --git a/apps/explorer/lib/release_tasks.ex b/apps/explorer/lib/release_tasks.ex
index 8d5a1b486c..1fcdc7fca8 100644
--- a/apps/explorer/lib/release_tasks.ex
+++ b/apps/explorer/lib/release_tasks.ex
@@ -14,7 +14,7 @@ defmodule Explorer.ReleaseTasks do
:ecto_sql
]
- @repos Application.compile_env(:blockscout, :ecto_repos, [Explorer.Repo])
+ @repos Application.compile_env(:blockscout, :ecto_repos, [Explorer.Repo, Explorer.Repo.Account])
def create_and_migrate do
start_services()
diff --git a/apps/explorer/priv/repo/migrations/20211031164954_create_account_identities.exs b/apps/explorer/priv/account/migrations/20211031164954_create_account_identities.exs
similarity index 73%
rename from apps/explorer/priv/repo/migrations/20211031164954_create_account_identities.exs
rename to apps/explorer/priv/account/migrations/20211031164954_create_account_identities.exs
index 1da855996a..fb571247f0 100644
--- a/apps/explorer/priv/repo/migrations/20211031164954_create_account_identities.exs
+++ b/apps/explorer/priv/account/migrations/20211031164954_create_account_identities.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.CreateAccountIdentities do
+defmodule Explorer.Repo.Account.Migrations.CreateAccountIdentities do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20211105114502_create_account_watchlists.exs b/apps/explorer/priv/account/migrations/20211105114502_create_account_watchlists.exs
similarity index 81%
rename from apps/explorer/priv/repo/migrations/20211105114502_create_account_watchlists.exs
rename to apps/explorer/priv/account/migrations/20211105114502_create_account_watchlists.exs
index 58924200fe..2e7c93f3cc 100644
--- a/apps/explorer/priv/repo/migrations/20211105114502_create_account_watchlists.exs
+++ b/apps/explorer/priv/account/migrations/20211105114502_create_account_watchlists.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.CreateAccountWatchlists do
+defmodule Explorer.Repo.Account.Migrations.CreateAccountWatchlists do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20211105130907_create_account_watchlist_addresses.exs b/apps/explorer/priv/account/migrations/20211105130907_create_account_watchlist_addresses.exs
similarity index 85%
rename from apps/explorer/priv/repo/migrations/20211105130907_create_account_watchlist_addresses.exs
rename to apps/explorer/priv/account/migrations/20211105130907_create_account_watchlist_addresses.exs
index 98f0aa9ac1..ef51c1850e 100644
--- a/apps/explorer/priv/repo/migrations/20211105130907_create_account_watchlist_addresses.exs
+++ b/apps/explorer/priv/account/migrations/20211105130907_create_account_watchlist_addresses.exs
@@ -1,10 +1,10 @@
-defmodule Explorer.Repo.Migrations.CreateAccountWatchlistAddresses do
+defmodule Explorer.Repo.Account.Migrations.CreateAccountWatchlistAddresses do
use Ecto.Migration
def change do
create table(:account_watchlist_addresses) do
add(:name, :string)
- add(:address_hash, references(:addresses, column: :hash, type: :bytea, on_delete: :delete_all))
+ add(:address_hash, :bytea, null: false)
add(:watchlist_id, references(:account_watchlists, on_delete: :delete_all))
add(:watch_coin_input, :boolean, default: true)
add(:watch_coin_output, :boolean, default: true)
diff --git a/apps/explorer/priv/repo/migrations/20211127212336_create_account_watchlist_notifications.exs b/apps/explorer/priv/account/migrations/20211127212336_create_account_watchlist_notifications.exs
similarity index 67%
rename from apps/explorer/priv/repo/migrations/20211127212336_create_account_watchlist_notifications.exs
rename to apps/explorer/priv/account/migrations/20211127212336_create_account_watchlist_notifications.exs
index 8310df5dfc..7d4af566fe 100644
--- a/apps/explorer/priv/repo/migrations/20211127212336_create_account_watchlist_notifications.exs
+++ b/apps/explorer/priv/account/migrations/20211127212336_create_account_watchlist_notifications.exs
@@ -1,15 +1,15 @@
-defmodule Explorer.Repo.Migrations.CreateAccountWatchlistNotifications do
+defmodule Explorer.Repo.Account.Migrations.CreateAccountWatchlistNotifications do
use Ecto.Migration
def change do
create table(:account_watchlist_notifications) do
add(:watchlist_address_id, references(:account_watchlist_addresses, on_delete: :delete_all))
- add(:transaction_hash, references(:transactions, column: :hash, type: :bytea, on_delete: :delete_all))
+ add(:transaction_hash, :bytea)
- add(:from_address_hash, references(:addresses, column: :hash, type: :bytea, on_delete: :delete_all))
+ add(:from_address_hash, :bytea)
- add(:to_address_hash, references(:addresses, column: :hash, type: :bytea, on_delete: :delete_all))
+ add(:to_address_hash, :bytea)
add(:direction, :string)
add(:name, :string)
diff --git a/apps/explorer/priv/repo/migrations/20211205220414_add_email_and_name_to_account_identity.exs b/apps/explorer/priv/account/migrations/20211205220414_add_email_and_name_to_account_identity.exs
similarity index 67%
rename from apps/explorer/priv/repo/migrations/20211205220414_add_email_and_name_to_account_identity.exs
rename to apps/explorer/priv/account/migrations/20211205220414_add_email_and_name_to_account_identity.exs
index bf87606d6c..0633e0dbae 100644
--- a/apps/explorer/priv/repo/migrations/20211205220414_add_email_and_name_to_account_identity.exs
+++ b/apps/explorer/priv/account/migrations/20211205220414_add_email_and_name_to_account_identity.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddEmailToAccountIdentity do
+defmodule Explorer.Repo.Account.Migrations.AddEmailToAccountIdentity do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220212222222_create_account_tag_addresses.exs b/apps/explorer/priv/account/migrations/20220212222222_create_account_tag_addresses.exs
similarity index 64%
rename from apps/explorer/priv/repo/migrations/20220212222222_create_account_tag_addresses.exs
rename to apps/explorer/priv/account/migrations/20220212222222_create_account_tag_addresses.exs
index 0a306516ff..df0074041e 100644
--- a/apps/explorer/priv/repo/migrations/20220212222222_create_account_tag_addresses.exs
+++ b/apps/explorer/priv/account/migrations/20220212222222_create_account_tag_addresses.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.CreateAccountTagAddresses do
+defmodule Explorer.Repo.Account.Migrations.CreateAccountTagAddresses do
use Ecto.Migration
def change do
@@ -6,10 +6,7 @@ defmodule Explorer.Repo.Migrations.CreateAccountTagAddresses do
add(:name, :string)
add(:identity_id, references(:account_identities, on_delete: :delete_all))
- add(
- :address_hash,
- references(:addresses, column: :hash, type: :bytea, on_delete: :delete_all)
- )
+ add(:address_hash, :bytea, null: false)
timestamps()
end
diff --git a/apps/explorer/priv/repo/migrations/20220313133333_create_account_tag_transactions.exs b/apps/explorer/priv/account/migrations/20220313133333_create_account_tag_transactions.exs
similarity index 64%
rename from apps/explorer/priv/repo/migrations/20220313133333_create_account_tag_transactions.exs
rename to apps/explorer/priv/account/migrations/20220313133333_create_account_tag_transactions.exs
index 49facab8c0..ba6fa338b9 100644
--- a/apps/explorer/priv/repo/migrations/20220313133333_create_account_tag_transactions.exs
+++ b/apps/explorer/priv/account/migrations/20220313133333_create_account_tag_transactions.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.CreateAccountTagTransactions do
+defmodule Explorer.Repo.Account.Migrations.CreateAccountTagTransactions do
use Ecto.Migration
def change do
@@ -6,10 +6,7 @@ defmodule Explorer.Repo.Migrations.CreateAccountTagTransactions do
add(:name, :string)
add(:identity_id, references(:account_identities, on_delete: :delete_all))
- add(
- :tx_hash,
- references(:transactions, column: :hash, type: :bytea, on_delete: :delete_all)
- )
+ add(:tx_hash, :bytea, null: false)
timestamps()
end
diff --git a/apps/explorer/priv/repo/migrations/20220324213333_add_subject_to_watchlist_notifications.exs b/apps/explorer/priv/account/migrations/20220324213333_add_subject_to_watchlist_notifications.exs
similarity index 64%
rename from apps/explorer/priv/repo/migrations/20220324213333_add_subject_to_watchlist_notifications.exs
rename to apps/explorer/priv/account/migrations/20220324213333_add_subject_to_watchlist_notifications.exs
index 7f644aaf87..6ff8a359ba 100644
--- a/apps/explorer/priv/repo/migrations/20220324213333_add_subject_to_watchlist_notifications.exs
+++ b/apps/explorer/priv/account/migrations/20220324213333_add_subject_to_watchlist_notifications.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddSubjectToWatchlistNotifications do
+defmodule Explorer.Repo.Account.Migrations.AddSubjectToWatchlistNotifications do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220407134152_add_api_keys_and_plans_tables.exs b/apps/explorer/priv/account/migrations/20220407134152_add_api_keys_and_plans_tables.exs
similarity index 93%
rename from apps/explorer/priv/repo/migrations/20220407134152_add_api_keys_and_plans_tables.exs
rename to apps/explorer/priv/account/migrations/20220407134152_add_api_keys_and_plans_tables.exs
index 245a077c43..11f23ffd61 100644
--- a/apps/explorer/priv/repo/migrations/20220407134152_add_api_keys_and_plans_tables.exs
+++ b/apps/explorer/priv/account/migrations/20220407134152_add_api_keys_and_plans_tables.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddApiKeysAndPlansTables do
+defmodule Explorer.Repo.Account.Migrations.AddApiKeysAndPlansTables do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220510094118_add_custom_abis_table.exs b/apps/explorer/priv/account/migrations/20220510094118_add_custom_abis_table.exs
similarity index 74%
rename from apps/explorer/priv/repo/migrations/20220510094118_add_custom_abis_table.exs
rename to apps/explorer/priv/account/migrations/20220510094118_add_custom_abis_table.exs
index a08b1cf365..a248c79458 100644
--- a/apps/explorer/priv/repo/migrations/20220510094118_add_custom_abis_table.exs
+++ b/apps/explorer/priv/account/migrations/20220510094118_add_custom_abis_table.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddCustomAbisTable do
+defmodule Explorer.Repo.Account.Migrations.AddCustomAbisTable do
use Ecto.Migration
def change do
@@ -6,7 +6,7 @@ defmodule Explorer.Repo.Migrations.AddCustomAbisTable do
add(:id, :serial, null: false, primary_key: true)
add(:identity_id, references(:account_identities, column: :id, on_delete: :delete_all), null: false)
add(:name, :string, null: false)
- add(:address_hash, references(:addresses, column: :hash, type: :bytea, on_delete: :delete_all), null: false)
+ add(:address_hash, :bytea, null: false)
add(:abi, :jsonb, null: false)
timestamps()
diff --git a/apps/explorer/priv/repo/migrations/20220606194836_add_account_public_tags_requests.exs b/apps/explorer/priv/account/migrations/20220606194836_add_account_public_tags_requests.exs
similarity index 88%
rename from apps/explorer/priv/repo/migrations/20220606194836_add_account_public_tags_requests.exs
rename to apps/explorer/priv/account/migrations/20220606194836_add_account_public_tags_requests.exs
index f1d95e9d01..dd0a9896b0 100644
--- a/apps/explorer/priv/repo/migrations/20220606194836_add_account_public_tags_requests.exs
+++ b/apps/explorer/priv/account/migrations/20220606194836_add_account_public_tags_requests.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddAccountPublicTagsRequests do
+defmodule Explorer.Repo.Account.Migrations.AddAccountPublicTagsRequests do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220620182600_add_account_identity_fields.exs b/apps/explorer/priv/account/migrations/20220620182600_add_account_identity_fields.exs
similarity index 71%
rename from apps/explorer/priv/repo/migrations/20220620182600_add_account_identity_fields.exs
rename to apps/explorer/priv/account/migrations/20220620182600_add_account_identity_fields.exs
index 2966c9dc59..1c7b13535f 100644
--- a/apps/explorer/priv/repo/migrations/20220620182600_add_account_identity_fields.exs
+++ b/apps/explorer/priv/account/migrations/20220620182600_add_account_identity_fields.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddAccountIdentityFields do
+defmodule Explorer.Repo.Account.Migrations.AddAccountIdentityFields do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220624142547_add_unique_constraints.exs b/apps/explorer/priv/account/migrations/20220624142547_add_unique_constraints.exs
similarity index 81%
rename from apps/explorer/priv/repo/migrations/20220624142547_add_unique_constraints.exs
rename to apps/explorer/priv/account/migrations/20220624142547_add_unique_constraints.exs
index a67b5dadbd..53293983d4 100644
--- a/apps/explorer/priv/repo/migrations/20220624142547_add_unique_constraints.exs
+++ b/apps/explorer/priv/account/migrations/20220624142547_add_unique_constraints.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.AddUniqueConstraints do
+defmodule Explorer.Repo.Account.Migrations.AddUniqueConstraints do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220811195240_migrate_public_tags_addresses_to_array.exs b/apps/explorer/priv/account/migrations/20220705195240_migrate_public_tags_addresses_to_array.exs
similarity index 91%
rename from apps/explorer/priv/repo/migrations/20220811195240_migrate_public_tags_addresses_to_array.exs
rename to apps/explorer/priv/account/migrations/20220705195240_migrate_public_tags_addresses_to_array.exs
index 0fa5f0e050..1282e2166c 100644
--- a/apps/explorer/priv/repo/migrations/20220811195240_migrate_public_tags_addresses_to_array.exs
+++ b/apps/explorer/priv/account/migrations/20220705195240_migrate_public_tags_addresses_to_array.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.MigratePublicTagsAddressesToArray do
+defmodule Explorer.Repo.Account.Migrations.MigratePublicTagsAddressesToArray do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/repo/migrations/20220729075714_guardiandb.exs b/apps/explorer/priv/account/migrations/20220729075714_guardiandb.exs
similarity index 83%
rename from apps/explorer/priv/repo/migrations/20220729075714_guardiandb.exs
rename to apps/explorer/priv/account/migrations/20220729075714_guardiandb.exs
index 21c3f9aead..fc058ff73b 100644
--- a/apps/explorer/priv/repo/migrations/20220729075714_guardiandb.exs
+++ b/apps/explorer/priv/account/migrations/20220729075714_guardiandb.exs
@@ -1,4 +1,4 @@
-defmodule Explorer.Repo.Migrations.CreateGuardianDBTokensTable do
+defmodule Explorer.Repo.Account.Migrations.CreateGuardianDBTokensTable do
use Ecto.Migration
def change do
diff --git a/apps/explorer/priv/account/migrations/20220901135656_copy_account_data.exs b/apps/explorer/priv/account/migrations/20220901135656_copy_account_data.exs
new file mode 100644
index 0000000000..2824c36607
--- /dev/null
+++ b/apps/explorer/priv/account/migrations/20220901135656_copy_account_data.exs
@@ -0,0 +1,92 @@
+defmodule Explorer.Repo.Account.Migrations.CopyAccountData do
+ use Ecto.Migration
+
+ def change do
+ execute("CREATE EXTENSION dblink;")
+ execute("SELECT dblink_connect('db_to_copy_from', '#{System.get_env("DATABASE_URL")}');")
+
+ execute(
+ "INSERT INTO account_identities
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_identities')
+ row(id bigint, uid character varying(255), inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone, email character varying(255), name character varying(255), plan_id bigint, nickname character varying(255), avatar text);"
+ )
+
+ # execute("INSERT INTO account_api_plans
+ # SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_api_plans')
+ # row(id integer, max_req_per_second smallint, name character varying(255), inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);")
+
+ execute(
+ "INSERT INTO account_api_keys
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_api_keys')
+ row(identity_id bigint, name character varying(255), value uuid, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute(
+ "INSERT INTO account_custom_abis
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_custom_abis')
+ row(id integer, identity_id bigint, name character varying(255), address_hash bytea, abi jsonb, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute(
+ "INSERT INTO account_public_tags_requests
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_public_tags_requests')
+ row(id integer, identity_id bigint, full_name character varying(255), email character varying(255), company character varying(255), website character varying(255), tags character varying(255), description text, additional_comment character varying(255), request_type character varying(255), is_owner boolean, remove_reason text, request_id character varying(255), inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone, addresses bytea[]);"
+ )
+
+ execute(
+ "INSERT INTO account_tag_addresses
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_tag_addresses')
+ row(id integer, name character varying(255), identity_id bigint, address_hash bytea, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute(
+ "INSERT INTO account_tag_transactions
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_tag_transactions')
+ row(id integer, name character varying(255), identity_id bigint, tx_hash bytea, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute(
+ "INSERT INTO account_watchlists
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_watchlists')
+ row(id bigint, name character varying(255), identity_id bigint, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute(
+ "INSERT INTO account_watchlist_addresses
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_watchlist_addresses')
+ row(id bigint, name character varying(255), address_hash bytea, watchlist_id bigint, watch_coin_input boolean, watch_coin_output boolean, watch_erc_20_input boolean, watch_erc_20_output boolean, watch_erc_721_input boolean, watch_erc_721_output boolean, watch_erc_1155_input boolean, watch_erc_1155_output boolean, notify_email boolean, notify_epns boolean, notify_feed boolean, notify_inapp boolean, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute(
+ "INSERT INTO account_watchlist_notifications
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM account_watchlist_notifications')
+ row(id bigint, watchlist_address_id bigint, transaction_hash bytea, from_address_hash bytea, to_address_hash bytea, direction character varying(255), name character varying(255), type character varying(255), method character varying(255), block_number integer, amount numeric, tx_fee numeric, viewed_at timestamp without time zone, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone, subject character varying(255));"
+ )
+
+ execute(
+ "INSERT INTO guardian_tokens
+ SELECT * FROM dblink('db_to_copy_from', 'SELECT * FROM guardian_tokens')
+ row(jti character varying(255), aud character varying(255), typ character varying(255), iss character varying(255), sub character varying(255), exp bigint, jwt text, claims jsonb, inserted_at timestamp(0) without time zone, updated_at timestamp(0) without time zone);"
+ )
+
+ execute("SELECT dblink_disconnect('db_to_copy_from');")
+ execute("DROP EXTENSION dblink;")
+
+ # update sequence id counter
+ execute("SELECT setval('account_identities_id_seq', (SELECT MAX(id) FROM account_identities)+1);")
+ execute("SELECT setval('account_custom_abis_id_seq', (SELECT MAX(id) FROM account_custom_abis)+1);")
+
+ execute(
+ "SELECT setval('account_public_tags_requests_id_seq', (SELECT MAX(id) FROM account_public_tags_requests)+1);"
+ )
+
+ execute("SELECT setval('account_tag_addresses_id_seq', (SELECT MAX(id) FROM account_tag_addresses)+1);")
+ execute("SELECT setval('account_tag_transactions_id_seq', (SELECT MAX(id) FROM account_tag_transactions)+1);")
+ execute("SELECT setval('account_watchlists_id_seq', (SELECT MAX(id) FROM account_watchlists)+1);")
+ execute("SELECT setval('account_watchlist_addresses_id_seq', (SELECT MAX(id) FROM account_watchlist_addresses)+1);")
+
+ execute(
+ "SELECT setval('account_watchlist_notifications_id_seq', (SELECT MAX(id) FROM account_watchlist_notifications)+1);"
+ )
+ end
+end
diff --git a/apps/explorer/test/explorer/account/notify/email_test.exs b/apps/explorer/test/explorer/account/notify/email_test.exs
index aff4baf42e..34e5a57ad6 100644
--- a/apps/explorer/test/explorer/account/notify/email_test.exs
+++ b/apps/explorer/test/explorer/account/notify/email_test.exs
@@ -60,7 +60,6 @@ defmodule Explorer.Account.Notify.EmailTest do
watchlist_address = %WatchlistAddress{
name: "wallet",
watchlist: watchlist,
- address: to_address,
address_hash: to_hash,
watch_coin_input: true,
watch_coin_output: true,
diff --git a/apps/explorer/test/explorer/account/notify/notify_test.exs b/apps/explorer/test/explorer/account/notify/notify_test.exs
index 1f97769a16..4d169f04d6 100644
--- a/apps/explorer/test/explorer/account/notify/notify_test.exs
+++ b/apps/explorer/test/explorer/account/notify/notify_test.exs
@@ -46,7 +46,7 @@ defmodule Explorer.Account.Notify.NotifyTest do
wn =
WatchlistNotification
|> first
- |> Repo.one()
+ |> Repo.account_repo().one()
assert notify == [[:ok]]
@@ -55,11 +55,11 @@ defmodule Explorer.Account.Notify.NotifyTest do
test "when address apears in watchlist" do
wa =
- %WatchlistAddress{
- address: address
- } = insert(:account_watchlist_address)
+ %WatchlistAddress{address_hash: address_hash} =
+ build(:account_watchlist_address)
+ |> Repo.account_repo().insert!()
- _watchlist_address = Repo.preload(wa, :address, watchlist: :identity)
+ _watchlist_address = Repo.preload(wa, watchlist: :identity)
tx =
%Transaction{
@@ -67,7 +67,7 @@ defmodule Explorer.Account.Notify.NotifyTest do
to_address: _to_address,
block_number: _block_number,
hash: _tx_hash
- } = with_block(insert(:transaction, to_address: address))
+ } = with_block(insert(:transaction, to_address: %Chain.Address{hash: address_hash}))
{_, fee} = Chain.fee(tx, :gwei)
amount = Wei.to(tx.value, :ether)
@@ -76,7 +76,7 @@ defmodule Explorer.Account.Notify.NotifyTest do
wn =
WatchlistNotification
|> first
- |> Repo.one()
+ |> Repo.account_repo().one()
assert notify == [[:ok]]
diff --git a/apps/explorer/test/support/data_case.ex b/apps/explorer/test/support/data_case.ex
index e12dd24a82..da18760983 100644
--- a/apps/explorer/test/support/data_case.ex
+++ b/apps/explorer/test/support/data_case.ex
@@ -34,9 +34,11 @@ defmodule Explorer.DataCase do
ExVCR.Config.cassette_library_dir("test/support/fixture/vcr_cassettes")
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo)
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Explorer.Repo.Account)
unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()})
+ Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo.Account, {:shared, self()})
end
Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.BlockNumber.child_id())
diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex
index 4d2c0d184f..12d0d7301f 100644
--- a/apps/explorer/test/support/factory.ex
+++ b/apps/explorer/test/support/factory.ex
@@ -126,7 +126,6 @@ defmodule Explorer.Factory do
def account_watchlist_factory do
%Watchlist{
- name: "default",
identity: build(:account_identity)
}
end
@@ -140,10 +139,12 @@ defmodule Explorer.Factory do
end
def account_watchlist_address_factory do
+ hash = build(:address).hash
+
%WatchlistAddress{
name: "wallet",
watchlist: build(:account_watchlist),
- address: build(:address),
+ address_hash: hash,
watch_coin_input: true,
watch_coin_output: true,
watch_erc_20_input: true,
diff --git a/apps/explorer/test/test_helper.exs b/apps/explorer/test/test_helper.exs
index 50847130f8..418ea17ea0 100644
--- a/apps/explorer/test/test_helper.exs
+++ b/apps/explorer/test/test_helper.exs
@@ -12,6 +12,7 @@ ExUnit.start()
{:ok, _} = Application.ensure_all_started(:ex_machina)
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, :auto)
+Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo.Account, :auto)
Mox.defmock(Explorer.ExchangeRates.Source.TestSource, for: Explorer.ExchangeRates.Source)
Mox.defmock(Explorer.KnownTokens.Source.TestSource, for: Explorer.KnownTokens.Source)
diff --git a/config/runtime/dev.exs b/config/runtime/dev.exs
index e7348f1e5d..3c69ee9c1a 100644
--- a/config/runtime/dev.exs
+++ b/config/runtime/dev.exs
@@ -46,10 +46,11 @@ database_api_url =
do: System.get_env("DATABASE_READ_ONLY_API_URL"),
else: System.get_env("DATABASE_URL")
-pool_size =
- if System.get_env("DATABASE_READ_ONLY_API_URL"),
- do: String.to_integer(System.get_env("POOL_SIZE", "40")),
- else: String.to_integer(System.get_env("POOL_SIZE", "50"))
+# pool_size =
+# if System.get_env("DATABASE_READ_ONLY_API_URL"),
+# do: String.to_integer(System.get_env("POOL_SIZE", "40")),
+# else: String.to_integer(System.get_env("POOL_SIZE", "50"))
+pool_size = String.to_integer(System.get_env("POOL_SIZE", "30"))
# Configure your database
config :explorer, Explorer.Repo,
@@ -63,7 +64,7 @@ hostname_api = if System.get_env("DATABASE_READ_ONLY_API_URL"), do: nil, else: h
pool_size_api =
if System.get_env("DATABASE_READ_ONLY_API_URL"),
- do: String.to_integer(System.get_env("POOL_SIZE_API", "50")),
+ do: String.to_integer(System.get_env("POOL_SIZE_API", "10")),
else: String.to_integer(System.get_env("POOL_SIZE_API", "10"))
# Configure API database
@@ -73,6 +74,23 @@ config :explorer, Explorer.Repo.Replica1,
url: database_api_url,
pool_size: pool_size_api
+database_account_url = System.get_env("DATABASE_ACCOUNT_URL") || System.get_env("DATABASE_URL")
+
+pool_size_account =
+ if System.get_env("DATABASE_ACCOUNT_URL"),
+ do: String.to_integer(System.get_env("POOL_SIZE_ACCOUNT", "10")),
+ else: String.to_integer(System.get_env("POOL_SIZE_ACCOUNT", "10"))
+
+database_account = if System.get_env("DATABASE_ACCOUNT_URL"), do: nil, else: database
+hostname_account = if System.get_env("DATABASE_ACCOUNT_URL"), do: nil, else: hostname
+
+# Configure Account database
+config :explorer, Explorer.Repo.Account,
+ database: database_account,
+ hostname: hostname_account,
+ url: database_account_url,
+ pool_size: pool_size_account
+
variant =
if is_nil(System.get_env("ETHEREUM_JSONRPC_VARIANT")) do
"ganache"
diff --git a/config/runtime/prod.exs b/config/runtime/prod.exs
index 8a5c8f24cd..43f07fde42 100644
--- a/config/runtime/prod.exs
+++ b/config/runtime/prod.exs
@@ -49,6 +49,15 @@ config :explorer, Explorer.Repo.Replica1,
pool_size: pool_size_api,
ssl: String.equivalent?(System.get_env("ECTO_USE_SSL") || "true", "true")
+database_account_url = System.get_env("DATABASE_ACCOUNT_URL")
+pool_size_account = String.to_integer(System.get_env("POOL_SIZE_ACCOUNT", "50"))
+
+# Configures Account database
+config :explorer, Explorer.Repo.Account,
+ url: database_account_url,
+ pool_size: pool_size_account,
+ ssl: String.equivalent?(System.get_env("ECTO_USE_SSL") || "true", "true")
+
variant =
if is_nil(System.get_env("ETHEREUM_JSONRPC_VARIANT")) do
"parity"
diff --git a/docker-compose/envs/common-blockscout.env b/docker-compose/envs/common-blockscout.env
index cd2a3ffdb0..babd98a2f9 100644
--- a/docker-compose/envs/common-blockscout.env
+++ b/docker-compose/envs/common-blockscout.env
@@ -124,3 +124,6 @@ API_RATE_LIMIT_STATIC_API_KEY=
FETCH_REWARDS_WAY=trace_block
ENABLE_RUST_VERIFICATION_SERVICE=true
RUST_VERIFICATION_SERVICE_URL=http://host.docker.internal:8043/
+# DATABASE_READ_ONLY_API_URL=
+# DATABASE_ACCOUNT_URL=
+# POOL_SIZE_ACCOUNT=
diff --git a/docker/Makefile b/docker/Makefile
index 9a5533f1bf..ada9d2dc40 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -502,7 +502,12 @@ endif
ifdef RUST_VERIFICATION_SERVICE_URL
BLOCKSCOUT_CONTAINER_PARAMS += -e 'RUST_VERIFICATION_SERVICE_URL=$(RUST_VERIFICATION_SERVICE_URL)'
endif
-
+ifdef DATABASE_ACCOUNT_URL
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'DATABASE_ACCOUNT_URL=$(DATABASE_ACCOUNT_URL)'
+endif
+ifdef POOL_SIZE_ACCOUNT
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'POOL_SIZE_ACCOUNT=$(POOL_SIZE_ACCOUNT)'
+endif
HAS_BLOCKSCOUT_IMAGE := $(shell docker images | grep -sw "${BS_CONTAINER_IMAGE} ")
build:
|