diff --git a/apps/explorer/lib/explorer/validator/metadata_importer.ex b/apps/explorer/lib/explorer/validator/metadata_importer.ex new file mode 100644 index 0000000000..3bf799d51c --- /dev/null +++ b/apps/explorer/lib/explorer/validator/metadata_importer.ex @@ -0,0 +1,36 @@ +defmodule Explorer.Validator.MetadataImporter do + @moduledoc """ + module that upserts validator metadata from a list of maps + """ + alias Explorer.Chain.Address + alias Explorer.Repo + + import Ecto.Query, only: [from: 2] + + def import_metadata(metadata_maps) do + Repo.transaction(fn -> Enum.each(metadata_maps, &upsert_validator_metadata(&1)) end) + end + + defp upsert_validator_metadata(validator_changeset) do + case Repo.get_by(Address.Name, address_hash: validator_changeset.address_hash, primary: true) do + nil -> + %Address.Name{} + |> Address.Name.changeset(validator_changeset) + |> Repo.insert() + + _address_name -> + query = + from(an in Address.Name, + update: [ + set: [ + name: ^validator_changeset.name, + metadata: ^validator_changeset.metadata + ] + ], + where: an.address_hash == ^validator_changeset.address_hash and an.primary == true + ) + + Repo.update_all(query, []) + end + end +end diff --git a/apps/explorer/test/explorer/validator/metadata_importer_test.exs b/apps/explorer/test/explorer/validator/metadata_importer_test.exs new file mode 100644 index 0000000000..281c45ec2f --- /dev/null +++ b/apps/explorer/test/explorer/validator/metadata_importer_test.exs @@ -0,0 +1,48 @@ +defmodule Explorer.Validator.MetadataImporterTest do + use Explorer.DataCase + + require Ecto.Query + + import Ecto.Query + import Explorer.Factory + + alias Explorer.Chain.Address + alias Explorer.Repo + alias Explorer.Validator.MetadataImporter + + describe "import_metadata/1" do + test "inserts new address names when there's none for the validators" do + address = insert(:address) + + [%{address_hash: address.hash, name: "Testinit Unitorius", primary: true, metadata: %{"test" => "toast"}}] + |> MetadataImporter.import_metadata() + + address_names = + from(an in Address.Name, where: an.address_hash == ^address.hash and an.primary == true) + |> Repo.all() + + expected_name = %Address.Name{address_hash: address.hash, name: "Testit Unitorus", metadata: %{"test" => "toast"}} + + assert length(address_names) == 1 + assert expected_name = hd(address_names) + end + + test "updates the primary address name if the validator already has one" do + address = insert(:address) + + insert(:address_name, address: address, primary: true, name: "Nodealus Faileddi") + + [%{address_hash: address.hash, name: "Testit Unitorus", primary: true, metadata: %{"test" => "toast"}}] + |> MetadataImporter.import_metadata() + + address_names = + from(an in Address.Name, where: an.address_hash == ^address.hash and an.primary == true) + |> Repo.all() + + expected_name = %Address.Name{address_hash: address.hash, name: "Testit Unitorus", metadata: %{"test" => "toast"}} + + assert length(address_names) == 1 + assert expected_name = hd(address_names) + end + end +end