diff --git a/apps/web/src/pages/blob/[hash].tsx b/apps/web/src/pages/blob/[hash].tsx index ff3ffb16a..1cfdbacb1 100644 --- a/apps/web/src/pages/blob/[hash].tsx +++ b/apps/web/src/pages/blob/[hash].tsx @@ -17,8 +17,10 @@ import type { DropdownProps, Option } from "~/components/Dropdown"; import type { DetailsLayoutProps } from "~/components/Layouts/DetailsLayout"; import { DetailsLayout } from "~/components/Layouts/DetailsLayout"; import { Link } from "~/components/Link"; +import { NavArrows } from "~/components/NavArrows"; import { BlockStatus } from "~/components/Status"; import { api } from "~/api-client"; +import Loading from "~/icons/loading.svg"; import type { Rollup } from "~/types"; import { buildBlockRoute, @@ -56,6 +58,21 @@ const Blob: NextPage = function () { (blobViewMode) => ({ value: blobViewMode }) ); + const enabled = Boolean(router.isReady && blob && blob.transactions[0]); + + const { data: neighbors } = api.blob.getBlobNeighbours.useQuery( + blob && blob.transactions[0] + ? { + commitment: blob.commitment, + } + : { + commitment: "", + }, + { + enabled, + } + ); + useEffect(() => { if (!decoder) { return; @@ -167,7 +184,25 @@ const Blob: NextPage = function () { return ( <> + Blob Details + {neighbors ? ( + + ) : ( + + )} + + } fields={blob ? detailsFields : undefined} /> ; + +export const getBlobNeighbours = publicProcedure + .input(inputSchema) + .query(async ({ input }) => { + const [next, prev] = await Promise.all([ + getBlobNeighbor(input, "next"), + getBlobNeighbor(input, "prev"), + ]); + + return { + next, + prev, + }; + }); + +async function getBlobNeighbor( + input: Input, + direction: "next" | "prev" +): Promise { + const blob = await prisma.blobsOnTransactions.findFirst({ + where: { + blob: { + commitment: input.commitment, + }, + }, + select: { + index: true, + blockNumber: true, + transaction: { + select: { + hash: true, + fromId: true, + index: true, + }, + }, + }, + }); + + if (!blob) { + return null; + } + + const nextBlobInTx = await prisma.blobsOnTransactions.findFirst({ + where: { + OR: [ + // Same transaction + { + txHash: blob.transaction.hash, + index: direction === "next" ? { gt: blob.index } : { lt: blob.index }, + }, + // Different transaction same block + blob.transaction.index + ? { + blockNumber: blob.blockNumber, + transaction: { + fromId: blob.transaction.fromId, + }, + txIndex: + direction === "next" + ? { gt: blob.transaction.index } + : { lt: blob.transaction.index }, + } + : {}, + // Different block + { + blockNumber: + direction === "next" + ? { gt: blob.blockNumber } + : { lt: blob.blockNumber }, + transaction: { + fromId: blob.transaction.fromId, + }, + }, + ], + }, + select: { + blobHash: true, + txIndex: true, + }, + orderBy: + direction === "next" + ? [{ blockNumber: "asc" }, { index: "asc" }, { txIndex: "asc" }] + : [{ blockNumber: "desc" }, { index: "desc" }, { txIndex: "desc" }], + }); + + if (nextBlobInTx) { + return nextBlobInTx.blobHash; + } + + return null; +} diff --git a/packages/api/src/routers/blob/index.ts b/packages/api/src/routers/blob/index.ts index 6d4ada4cf..3faf4400d 100644 --- a/packages/api/src/routers/blob/index.ts +++ b/packages/api/src/routers/blob/index.ts @@ -1,12 +1,14 @@ import { t } from "../../trpc-client"; import { getAll } from "./getAll"; import { getBlobDataByBlobId } from "./getBlobDataByBlobId"; +import { getBlobNeighbours } from "./getBlobNeighbours"; import { getByBlobId } from "./getByBlobId"; import { getCount } from "./getCount"; export const blobRouter = t.router({ getAll, getByBlobId, + getBlobNeighbours, getBlobDataByBlobId, getCount, });