Skip to content

Commit 57f35f9

Browse files
committed
feat: aggregated proof view
1 parent 9760145 commit 57f35f9

5 files changed

Lines changed: 181 additions & 10 deletions

File tree

explorer/lib/explorer/models/aggregated_proofs.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,6 @@ defmodule AggregatedProofs do
6262
end
6363

6464
def get_aggregated_proof_by_number(number) do
65-
Explorer.Repo.get_by(AggregatedProofs, number: agg_proof.number)
65+
Explorer.Repo.get_by(AggregatedProofs, number: number)
6666
end
6767
end

explorer/lib/explorer/models/aggregation_mode_proof.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defmodule AggregationModeProof do
22
require Logger
33
use Ecto.Schema
44
import Ecto.Changeset
5+
import Ecto.Query
56

67
# Different from proofs.ex (we could use the same but the hashes are constructed different)
78
@primary_key {:id, :id, autogenerate: true}
@@ -47,7 +48,7 @@ defmodule AggregationModeProof do
4748
def get_all_proof_hashes(agg_proof_number) do
4849
query =
4950
from(proof in AggregationModeProof,
50-
where: proof.aggregated_proof_number == agg_proof_number,
51+
where: proof.aggregated_proof_number == ^agg_proof_number,
5152
select: proof.proof_hash
5253
)
5354

explorer/lib/explorer_web/components/core_components.ex

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,39 @@ defmodule ExplorerWeb.CoreComponents do
497497
"""
498498
end
499499

500+
@doc """
501+
Renders a dynamic badge component for the batcher.
502+
"""
503+
attr(:class, :string, default: nil)
504+
attr(:status, :integer)
505+
slot(:inner_block, default: nil)
506+
507+
def dynamic_badge_for_agg_proof(assigns) do
508+
~H"""
509+
<.badge
510+
variant={
511+
case @status do
512+
0 -> "accent"
513+
1 -> "destructive"
514+
2 -> "foreground"
515+
end
516+
}
517+
class={
518+
classes([
519+
@class
520+
])
521+
}
522+
>
523+
<%= case @status do
524+
0 -> "Verified"
525+
1 -> "Failed"
526+
2 -> "Missed"
527+
end %>
528+
<%= render_slot(@inner_block) %>
529+
</.badge>
530+
"""
531+
end
532+
500533
@doc """
501534
Renders a selector dropdown on hover component with buttons that trigger actions on click.
502535

explorer/lib/explorer_web/live/pages/agg_proofs/index.ex

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,26 @@ defmodule ExplorerWeb.AggProofs.Index do
55
@impl true
66
def mount(%{"proof_number" => proof_number}, _, socket) do
77
agg_proof =
8-
Explorer.AggregatedProofs.get_aggregated_proof_by_number(proof_number)
9-
10-
proofs = Explorer.AggregationModeProof.get_all_proof_hashes(proof_number)
8+
AggregatedProofs.get_aggregated_proof_by_number(proof_number)
119

1210
{
1311
:ok,
1412
assign(
1513
socket,
1614
agg_proof: agg_proof,
17-
proofs: proofs
15+
proof_hashes: :empty
1816
)
1917
}
2018
end
19+
20+
@impl true
21+
def handle_event("show_proofs", _value, socket) do
22+
proofs = AggregationModeProof.get_all_proof_hashes(socket.assigns.agg_proof.number)
23+
{:noreply, assign(socket, proof_hashes: proofs)}
24+
end
25+
26+
@impl true
27+
def handle_event("hide_proofs", _value, socket) do
28+
{:noreply, assign(socket, proof_hashes: :empty)}
29+
end
2130
end
Lines changed: 132 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,133 @@
1-
<div>
2-
<h1>
3-
AGGREGATED PROOF DETAILS
4-
</h1>
1+
<div class="flex flex-col space-y-3 px-1 text-foreground max-w-[27rem] sm:max-w-3xl md:max-w-5xl mx-auto capitalize">
2+
<%= if @agg_proof != :empty do %>
3+
<.card_preheding class="text-4xl sm:text-5xl font-bold font-foreground">
4+
Aggregated proof details
5+
</.card_preheding>
6+
<.card
7+
class="relative px-4 py-5 min-h-fit flex flex-col"
8+
inner_class="font-semibold inline-flex flex-col text-base gap-y-4 text-muted-foreground [&>div>p]:text-foreground [&>div>a]:text-foreground [&>div>*]:break-all [&>div>*]:font-normal [&>div]:flex [&>div]:flex-col [&>div]:lg:flex-row [&>div>h3]:basis-1/4"
9+
>
10+
<div>
11+
<h3>
12+
Merkle root:
13+
</h3>
14+
<p class="flex flex-wrap md:items-center md:gap-x-2">
15+
<%= @agg_proof.merkle_root %>
16+
<.live_component
17+
module={CopyToClipboardButtonComponent}
18+
text_to_copy={@agg_proof.merkle_root}
19+
id={"copy_batch_hash_#{@agg_proof.merkle_root}"}
20+
class="inline-flex"
21+
/>
22+
</p>
23+
</div>
24+
25+
<div>
26+
<h3>
27+
Status:
28+
</h3>
29+
<.dynamic_badge_for_agg_proof class="w-fit" status={@agg_proof.status} />
30+
</div>
31+
<div>
32+
<h3>
33+
Number of Proofs included:
34+
</h3>
35+
<p><%= @agg_proof.number_of_proofs %></p>
36+
</div>
37+
38+
<div>
39+
<h3>
40+
Proofs included:
41+
</h3>
42+
<%= if @proof_hashes != :empty do %>
43+
<%= if @proof_hashes == :nil do %>
44+
<p class="normal-case">
45+
Proofs couldn't be shown for this aggregated proof
46+
</p>
47+
<% else %>
48+
<div class="space-y-2 basis-3/4">
49+
<div class="h-36 overflow-y-auto text-foreground space-y-2">
50+
<p :for={{proof, index} <- Enum.with_index(@proof_hashes)}>
51+
<%= proof %>
52+
<.live_component
53+
module={CopyToClipboardButtonComponent}
54+
text_to_copy={proof}
55+
id={"copy_proof_batch_hash_#{proof}_#{Utils.random_id("cp_#{index}")}"}
56+
class="inline-flex"
57+
/>
58+
</p>
59+
</div>
60+
<.button class="w-fit text-foreground" phx-click="hide_proofs">
61+
<.icon name="hero-eye-slash" class="size-4" /> Hide Proofs
62+
</.button>
63+
</div>
64+
<% end %>
65+
<% else %>
66+
<.button class="w-fit text-foreground font-semibold" phx-click="show_proofs">
67+
<.icon name="hero-eye" class="size-4" /> Show Proofs
68+
</.button>
69+
<% end %>
70+
</div>
71+
<.divider />
72+
<div>
73+
<h3>
74+
Block Number:
75+
</h3>
76+
<.a
77+
target="_blank"
78+
rel="noopener"
79+
href={
80+
"#{Helpers.get_etherescan_url()}/block/#{@agg_proof.block_number}"
81+
}
82+
class="hover:text-foreground/80"
83+
>
84+
<%= @agg_proof.block_number |> Helpers.format_number() %>
85+
</.a>
86+
</div>
87+
<div>
88+
<h3>
89+
Transaction Hash:
90+
</h3>
91+
<.a
92+
target="_blank"
93+
rel="noopener"
94+
href={"#{Helpers.get_etherescan_url()}/tx/#{@agg_proof.tx_hash}"}
95+
class="hover:text-foreground/80"
96+
>
97+
<%= @agg_proof.tx_hash %>
98+
</.a>
99+
</div>
100+
101+
<div>
102+
<h3>
103+
Blob versioned hash:
104+
</h3>
105+
<.a
106+
target="_blank"
107+
rel="noopener"
108+
href={"#{Helpers.get_etherescan_url()}/blob/#{@agg_proof.blob_versioned_hash}"}
109+
class="hover:text-foreground/80"
110+
>
111+
<%= @agg_proof.blob_versioned_hash %>
112+
</.a>
113+
</div>
114+
</.card>
115+
<% else %>
116+
<div class="flex flex-col space-y-6 justify-center grow relative text-center md:pt-14">
117+
<h1 class="text-5xl font-semibold">Oops!</h1>
118+
<h2 class="text-xl font-medium">
119+
The batch you are looking for <br /> doesn't exist.
120+
</h2>
121+
<img
122+
class="z-0 w-64 rounded-xl mx-auto"
123+
alt="block not found"
124+
src={~p"/images/not-found.webp"}
125+
/>
126+
<.link navigate={~p"/"}>
127+
<.button>
128+
Go Home
129+
</.button>
130+
</.link>
131+
</div>
132+
<% end %>
5133
</div>

0 commit comments

Comments
 (0)