From f95001d196f3f107ca24050fb9ddc6c72fcecda2 Mon Sep 17 00:00:00 2001 From: William Law Date: Mon, 20 Apr 2026 19:04:25 -0400 Subject: [PATCH] spike --- .../api/bundle/{[uuid] => [hash]}/route.ts | 10 +++--- src/app/bundles/{[uuid] => [hash]}/page.tsx | 20 +++++------ src/lib/s3.ts | 36 ++++++++++++------- 3 files changed, 39 insertions(+), 27 deletions(-) rename src/app/api/bundle/{[uuid] => [hash]}/route.ts (83%) rename src/app/bundles/{[uuid] => [hash]}/page.tsx (98%) diff --git a/src/app/api/bundle/[uuid]/route.ts b/src/app/api/bundle/[hash]/route.ts similarity index 83% rename from src/app/api/bundle/[uuid]/route.ts rename to src/app/api/bundle/[hash]/route.ts index 6be37d6d..3d9e3f69 100644 --- a/src/app/api/bundle/[uuid]/route.ts +++ b/src/app/api/bundle/[hash]/route.ts @@ -2,18 +2,18 @@ import { type NextRequest, NextResponse } from "next/server"; import { type BundleEvent, getBundleHistory } from "@/lib/s3"; export interface BundleHistoryResponse { - uuid: string; + hash: string; history: BundleEvent[]; } export async function GET( _request: NextRequest, - { params }: { params: Promise<{ uuid: string }> }, + { params }: { params: Promise<{ hash: string }> }, ) { try { - const { uuid } = await params; + const { hash } = await params; - const bundle = await getBundleHistory(uuid); + const bundle = await getBundleHistory(hash); if (!bundle) { return NextResponse.json({ error: "Bundle not found" }, { status: 404 }); } @@ -24,7 +24,7 @@ export async function GET( ); const response: BundleHistoryResponse = { - uuid, + hash, history: bundle.history, }; diff --git a/src/app/bundles/[uuid]/page.tsx b/src/app/bundles/[hash]/page.tsx similarity index 98% rename from src/app/bundles/[uuid]/page.tsx rename to src/app/bundles/[hash]/page.tsx index 50ed6487..289ecbd2 100644 --- a/src/app/bundles/[uuid]/page.tsx +++ b/src/app/bundles/[hash]/page.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { useEffect, useState } from "react"; -import type { BundleHistoryResponse } from "@/app/api/bundle/[uuid]/route"; +import type { BundleHistoryResponse } from "@/app/api/bundle/[hash]/route"; import type { BundleTransaction, MeterBundleResponse } from "@/lib/s3"; const WEI_PER_GWEI = 10n ** 9n; @@ -10,7 +10,7 @@ const WEI_PER_ETH = 10n ** 18n; const BLOCK_EXPLORER_URL = process.env.NEXT_PUBLIC_BLOCK_EXPLORER_URL; interface PageProps { - params: Promise<{ uuid: string }>; + params: Promise<{ hash: string }>; } function formatBigInt(value: bigint, decimals: number, scale: bigint): string { @@ -474,21 +474,21 @@ function SectionTitle({ children }: { children: React.ReactNode }) { } export default function BundlePage({ params }: PageProps) { - const [uuid, setUuid] = useState(""); + const [hash, setHash] = useState(""); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { - params.then((p) => setUuid(p.uuid)); + params.then((p) => setHash(p.hash)); }, [params]); useEffect(() => { - if (!uuid) return; + if (!hash) return; const fetchData = async () => { try { - const response = await fetch(`/api/bundle/${uuid}`); + const response = await fetch(`/api/bundle/${hash}`); if (!response.ok) { setError( response.status === 404 @@ -511,9 +511,9 @@ export default function BundlePage({ params }: PageProps) { fetchData(); const interval = setInterval(fetchData, 5000); return () => clearInterval(interval); - }, [uuid]); + }, [hash]); - if (!uuid || (loading && !data)) { + if (!hash || (loading && !data)) { return (
@@ -564,9 +564,9 @@ export default function BundlePage({ params }: PageProps) {
- {uuid} + {hash} - +
diff --git a/src/lib/s3.ts b/src/lib/s3.ts index a3bd03cc..47eb1c47 100644 --- a/src/lib/s3.ts +++ b/src/lib/s3.ts @@ -163,24 +163,36 @@ export interface BundleHistory { } export async function getBundleHistory( - bundleId: string, + bundleKey: string, ): Promise { - const key = `bundles/${bundleId}`; - const content = await getObjectContent(key); + const prefix = `bundles/${bundleKey}/`; + const listCommand = new ListObjectsV2Command({ + Bucket: BUCKET_NAME, + Prefix: prefix, + }); - if (!content) { + const listResponse = await s3Client.send(listCommand); + const keys = listResponse.Contents?.map((obj) => obj.Key).filter( + Boolean, + ) as string[]; + + if (!keys || keys.length === 0) { return null; } - try { - return JSON.parse(content) as BundleHistory; - } catch (error) { - console.error( - `Failed to parse bundle history for bundle ${bundleId}:`, - error, - ); - return null; + const history: BundleEvent[] = []; + for (const key of keys) { + const content = await getObjectContent(key); + if (content) { + try { + history.push(JSON.parse(content) as BundleEvent); + } catch (error) { + console.error(`Failed to parse event at ${key}:`, error); + } + } } + + return { history }; } export interface BlockTransaction {