diff --git a/explorer/lib/explorer/models/aggregated_proofs.ex b/explorer/lib/explorer/models/aggregated_proofs.ex index d43dc34efd..df4e87b6c0 100644 --- a/explorer/lib/explorer/models/aggregated_proofs.ex +++ b/explorer/lib/explorer/models/aggregated_proofs.ex @@ -67,13 +67,25 @@ defmodule AggregatedProofs do Explorer.Repo.get_by(AggregatedProofs, id: id) end + def get_newest_aggregated_proof_by_merkle_root(merkle_root) do + query = + from(proof in AggregatedProofs, + select: proof, + where: proof.merkle_root == ^merkle_root, + order_by: [desc: proof.block_number], + limit: 1 + ) + + Explorer.Repo.one(query) + end + def get_paginated_proofs(%{page: page, page_size: size}) do query = from(proof in AggregatedProofs, + select: proof, order_by: [desc: proof.block_number], limit: ^size, - offset: ^((page - 1) * size), - select: proof + offset: ^((page - 1) * size) ) Explorer.Repo.all(query) diff --git a/explorer/lib/explorer/models/aggregation_mode_proof.ex b/explorer/lib/explorer/models/aggregation_mode_proof.ex index 947982cf4d..07e2ece6e7 100644 --- a/explorer/lib/explorer/models/aggregation_mode_proof.ex +++ b/explorer/lib/explorer/models/aggregation_mode_proof.ex @@ -52,10 +52,22 @@ defmodule AggregationModeProof do def get_all_proof_hashes(id) do query = from(proof in AggregationModeProof, - where: proof.agg_proof_id == ^id, - select: proof.proof_hash + select: proof.proof_hash, + where: proof.agg_proof_id == ^id ) Explorer.Repo.all(query) end + + def get_newest_proof_by_hash(hash) do + query = + from(proof in AggregationModeProof, + select: proof, + where: proof.proof_hash == ^hash, + order_by: [desc: proof.inserted_at], + limit: 1 + ) + + Explorer.Repo.one(query) + end end diff --git a/explorer/lib/explorer_web/components/search.ex b/explorer/lib/explorer_web/components/search.ex index 7babfcbd5d..2b0cdd82b7 100644 --- a/explorer/lib/explorer_web/components/search.ex +++ b/explorer/lib/explorer_web/components/search.ex @@ -1,24 +1,44 @@ defmodule SearchComponent do + require Logger use ExplorerWeb, :live_component @impl true - def handle_event("search_batch", %{"batch" => %{"merkle_root" => input_hash}}, socket) do - input_hash + def handle_event("search_batch", %{"search" => search}, socket) do + search |> (fn hash -> if String.match?(hash, ~r/^0x[a-fA-F0-9]+$/), do: {:ok, hash}, else: :invalid_hash end).() |> case do {:ok, hash} -> - case Proofs.get_number_of_batches_containing_proof(hash) do - 0 -> {:noreply, push_navigate(socket, to: ~p"/batches/#{hash}")} - _ -> {:noreply, push_navigate(socket, to: ~p"/search?q=#{hash}")} + cond do + # See if the hash belongs to a proof in a batch + # If so, redirect to search to show all the batches where this proofs exists + Proofs.get_number_of_batches_containing_proof(hash) > 0 -> + {:noreply, push_navigate(socket, to: ~p"/search?q=#{hash}")} + + # See if the hash belongs to the root of a batch + Batches.get_batch(%{merkle_root: hash}) != nil -> + {:noreply, push_navigate(socket, to: ~p"/batches/#{hash}")} + + # See if the hash belongs to an aggregated proof merkle root + (proof = AggregatedProofs.get_newest_aggregated_proof_by_merkle_root(hash)) != nil -> + {:noreply, push_navigate(socket, to: ~p"/aggregated_proofs/#{proof.id}")} + + # Finally, see if the hash belongs to a proof of an aggregated proof + (proof = AggregationModeProof.get_newest_proof_by_hash(hash)) != nil -> + {:noreply, push_navigate(socket, to: ~p"/aggregated_proofs/#{proof.agg_proof_id}")} + + # Otherwise inform the user nothing was found + true -> + {:noreply, + socket + |> put_flash!(:error, "No batch or proof was found with the provided hash.")} end :invalid_hash -> {:noreply, socket - |> assign(batch_merkle_root: input_hash) - |> put_flash!(:error, "Please enter a valid proof batch hash (0x69...).")} + |> put_flash!(:error, "Please enter a valid hash (0x69...).")} end end @@ -42,8 +62,8 @@ defmodule SearchComponent do id={"input_#{assigns.id}"} class="pr-10 w-full text-foreground rounded-lg border-foreground/20 bg-card focus:border-foreground/20 focus:ring-accent text-sm" type="search" - placeholder="Search batch by batch hash or proof hash" - name="batch[merkle_root]" + placeholder="Search by batch hash or proof hash" + name="search" /> <.icon name="hero-magnifying-glass-solid" class="absolute right-3 text-foreground/20 size-5 hover:text-foreground" /> diff --git a/explorer/lib/explorer_web/live/pages/search/index.ex b/explorer/lib/explorer_web/live/pages/search/index.ex index ad5abf20a4..37d83cb41a 100644 --- a/explorer/lib/explorer_web/live/pages/search/index.ex +++ b/explorer/lib/explorer_web/live/pages/search/index.ex @@ -52,25 +52,27 @@ defmodule ExplorerWeb.Search.Index do Search Results for "<%= @hash |> Helpers.shorten_hash() %>" <%= if @results != nil or @results != [] do %> - <.table id="results" rows={@results}> - <:col :let={result} label="Batch Hash" class="text-left"> - <.link - navigate={~p"/batches/#{result}"} - class="flex justify-between group group-hover:text-foreground/80" - > - - - <%= result |> Helpers.shorten_hash(12) %> - - <.right_arrow /> - <.tooltip> - <%= result %> - - - - + <.card_background> + <.table id="results" rows={@results}> + <:col :let={result} label="Batch Hash" class="text-left"> + <.link + navigate={~p"/batches/#{result}"} + class="flex justify-between group group-hover:text-foreground/80" + > + + + <%= result |> Helpers.shorten_hash(12) %> + + <.right_arrow /> + <.tooltip> + <%= result %> + + + + +
<%= if @current_page != 1 do %> <.link patch={~p"/search?q=#{@hash}&page=#{@current_page - 1}"}>