From 1d9034667d4802c049921e7fe04e4fe1e80e3012 Mon Sep 17 00:00:00 2001 From: Marc N Date: Sun, 21 Apr 2024 14:16:22 +0200 Subject: [PATCH] feat: show blobs from DB in interface --- frontend/src/app/page.tsx | 19 +++++++++-------- frontend/src/components/BlobData.tsx | 9 ++++---- frontend/src/components/FusedBlobList.tsx | 20 +++++++----------- frontend/src/components/PartialBlob.tsx | 4 ++-- frontend/src/components/UnfusedBlobList.tsx | 2 +- frontend/src/data/api.ts | 16 +++++++------- frontend/src/data/useLatestBlobs.ts | 2 +- frontend/src/lib/types.ts | 2 +- src/api/blobs/blobRouter.ts | 4 +++- .../blobs/fusedBlob/fusedBlobRepository.ts | 19 ++++++++++------- .../partialBlob/partialBlobRepository.ts | 21 ++++++++++++------- src/blob-fuser/index.ts | 15 +++++++++++-- 12 files changed, 77 insertions(+), 56 deletions(-) diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 3276588..f9012a1 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -2,13 +2,7 @@ import { useEffect, useState } from "react"; import { toast } from "sonner"; -import { - formatEther, - formatGwei, - isAddress, - parseEther, - parseGwei, -} from "viem"; +import { formatEther, isAddress, parseEther } from "viem"; import { useAccount, useConnect, @@ -25,6 +19,7 @@ import Header from "@/components/Header"; import NewBlobDialog, { newBlobFormSchema } from "@/components/NewBlobDialog"; import UserInfo from "@/components/UserInfo"; import { useUserBalance } from "@/data/useUserBalance"; +import { useLatestBlobs } from "@/data/useLatestBlobs"; const blobs = [ { @@ -68,12 +63,18 @@ const Home = () => { const { chains, switchChainAsync } = useSwitchChain(); const { data: userBalance, error } = useUserBalance({ address }); + const { data: blobs, error: blobsError } = useLatestBlobs(); + const { fusedBlobs = [], partialBlobs = [] } = blobs ?? {}; useEffect(() => { if (error) { console.log(error); } - }, [error]); + + if (blobsError) { + console.log(blobsError); + } + }, [error, blobsError]); const onSubmitAddFunds = async ( values: z.infer, @@ -129,7 +130,7 @@ const Home = () => { onConnectWalletClick={() => connect({ connector: connectors?.[0] })} /> - + = ({ blobs }) => { +const BlobData: React.FC = ({ partialBlobs, fusedBlobs }) => { return (
- - + +
); }; diff --git a/frontend/src/components/FusedBlobList.tsx b/frontend/src/components/FusedBlobList.tsx index 74be11d..9b61fbe 100644 --- a/frontend/src/components/FusedBlobList.tsx +++ b/frontend/src/components/FusedBlobList.tsx @@ -8,11 +8,6 @@ import { PartialBlob as PartialBlobType } from "@/lib/types"; import { PartialBlob } from "./PartialBlob"; -const tx = [ - "0x222d39Ec6bb596229938210a0D57E5C17f479495", - "0x222d39Ec6bb596229938210a0D57E5C17f479495", - "0x222d39Ec6bb596229938210a0D57E5C17f479495", -]; const FusedBlobList: React.FC<{ blobs: PartialBlobType[] }> = ({ blobs }) => (

Fused Blobs

@@ -21,26 +16,25 @@ const FusedBlobList: React.FC<{ blobs: PartialBlobType[] }> = ({ blobs }) => ( collapsible className="max-w-[650px] overflow-hidden rounded-sm" > - {tx.map((address, index) => ( + {blobs.map(({ id, txHash, partialBlobs }) => ( -
- {" "} - {address} +
+ {txHash ?? "Pending..."}
- {blobs.slice(0, 3).map((blob, index) => ( + {partialBlobs.map((blob, index) => ( ))}
diff --git a/frontend/src/components/PartialBlob.tsx b/frontend/src/components/PartialBlob.tsx index 6e4886b..19a0814 100644 --- a/frontend/src/components/PartialBlob.tsx +++ b/frontend/src/components/PartialBlob.tsx @@ -5,7 +5,7 @@ import { Badge } from "./ui/badge"; export const PartialBlob: React.FC = ({ fromAddress, size, - bid, + bidInGwei, }) => (
@@ -16,7 +16,7 @@ export const PartialBlob: React.FC = ({ {size} bytes - {bid} gwei + {bidInGwei.toString()} gwei
diff --git a/frontend/src/components/UnfusedBlobList.tsx b/frontend/src/components/UnfusedBlobList.tsx index b4f3d1c..c931387 100644 --- a/frontend/src/components/UnfusedBlobList.tsx +++ b/frontend/src/components/UnfusedBlobList.tsx @@ -11,7 +11,7 @@ const UnfusedBlobList: React.FC<{ blobs: PartialBlobType[] }> = ({ blobs }) => ( key={index} fromAddress={blob.fromAddress} size={blob.size} - bid={blob.bid} + bidInGwei={blob.bidInGwei} /> ))}
diff --git a/frontend/src/data/api.ts b/frontend/src/data/api.ts index a6aab17..47c1e1c 100644 --- a/frontend/src/data/api.ts +++ b/frontend/src/data/api.ts @@ -27,26 +27,28 @@ export const getUser = ({ address }: { address: Hex }) => { const partialBlobSchema = z.object({ id: z.number(), size: z.number(), - bidInGwei: z.number(), - costInGwei: z.number().nullable(), + bidInGwei: z.coerce.bigint(), + costInGwei: z.coerce.bigint().nullable(), fromAddress: z.string(), fusedBlobId: z.number().nullable(), }); const fusedBlobSchema = z.object({ id: z.number(), - txHash: z.string(), - totalCostInGwei: z.number().nullable(), - fusedBlobs: z.array(partialBlobSchema), + txHash: z.string().nullable(), + totalCostInGwei: z.coerce.bigint().nullable(), + partialBlobs: z.array(partialBlobSchema), }); const latestBlobSchema = z.object({ - unfusedBlobs: z.array(partialBlobSchema), + partialBlobs: z.array(partialBlobSchema), fusedBlobs: z.array(fusedBlobSchema), }); export const getLatestBlobs = async () => { - return api.get("/blobs").then((res) => latestBlobSchema.parse(res.data.data)); + return api.get("/blobs").then((res) => { + return latestBlobSchema.parse(res.data.data); + }); }; export const submitBlob = (data: PartialBlobSubmission) => { diff --git a/frontend/src/data/useLatestBlobs.ts b/frontend/src/data/useLatestBlobs.ts index 17b4a95..1e7602b 100644 --- a/frontend/src/data/useLatestBlobs.ts +++ b/frontend/src/data/useLatestBlobs.ts @@ -7,6 +7,6 @@ export const useLatestBlobs = () => { queryKey: ["blobs"], queryFn: () => getLatestBlobs(), placeholderData: keepPreviousData, - refetchInterval: 5000, + refetchInterval: 10000, }); }; diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index d02c3e7..464faa8 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -1,5 +1,5 @@ export interface PartialBlob { fromAddress: string; size: number; - bid: number; + bidInGwei: number; } diff --git a/src/api/blobs/blobRouter.ts b/src/api/blobs/blobRouter.ts index 92ee1d8..0ae2407 100644 --- a/src/api/blobs/blobRouter.ts +++ b/src/api/blobs/blobRouter.ts @@ -31,7 +31,9 @@ export const blobRouter: Router = (() => { router.get("/", async (_req: Request, res: Response) => { const [partialBlobs, fusedBlobs] = await Promise.all([ - partialBlobRepository.findAllAsync({ withDataAndSignature: false }), + partialBlobRepository.findAllUnfusedAsync({ + withDataAndSignature: false, + }), fusedBlobRepository.findAllAsync({ withDataAndSignature: false }), ]); diff --git a/src/api/blobs/fusedBlob/fusedBlobRepository.ts b/src/api/blobs/fusedBlob/fusedBlobRepository.ts index 6f5df7d..34aa09f 100644 --- a/src/api/blobs/fusedBlob/fusedBlobRepository.ts +++ b/src/api/blobs/fusedBlob/fusedBlobRepository.ts @@ -2,6 +2,7 @@ import { type Hex } from "viem"; import { type PartialBlob } from "@/api/blobs/partialBlob/partialBlobModel"; import { prisma } from "@/api/prisma/client"; +import { getLengthWithExtraBytes } from "@/blob-fuser"; import { convertPartialBlobInDBToPartialBlob } from "../partialBlob/convertPartialBlobInDBToPartialBlob"; import { type FusedBlob } from "./fusedBlobModel"; @@ -17,15 +18,19 @@ export const fusedBlobRepository = { return fusedBlobsInDB.map((fusedBlob) => ({ ...fusedBlob, partialBlobs: fusedBlob.partialBlobs.map((partialBlob) => { - if (!withDataAndSignature) { - return { - ...partialBlob, - data: null, - signature: null, - }; + const convertedPartialBlob = + convertPartialBlobInDBToPartialBlob(partialBlob); + + if (withDataAndSignature) { + return convertedPartialBlob; } - return convertPartialBlobInDBToPartialBlob(partialBlob); + return { + ...convertedPartialBlob, + data: null, + signature: null, + size: getLengthWithExtraBytes(convertedPartialBlob.data), + }; }), })); }, diff --git a/src/api/blobs/partialBlob/partialBlobRepository.ts b/src/api/blobs/partialBlob/partialBlobRepository.ts index dbebe67..9a20d14 100644 --- a/src/api/blobs/partialBlob/partialBlobRepository.ts +++ b/src/api/blobs/partialBlob/partialBlobRepository.ts @@ -1,6 +1,7 @@ import { Hex } from "viem"; import { prisma } from "@/api/prisma/client"; +import { getLengthWithExtraBytes } from "@/blob-fuser"; import { convertHexToBuffer, @@ -38,10 +39,20 @@ export const partialBlobRepository = { return convertPartialBlobInDBToPartialBlob(partialBlobInDB); }, - findAllAsync: async ({ withDataAndSignature = true } = {}): Promise< + findAllAsync: async (): Promise< PartialBlobWithNullableDataAndSignature[] > => { const partialBlobsInDB = await prisma.partialBlob.findMany(); + return partialBlobsInDB.map(convertPartialBlobInDBToPartialBlob); + }, + + findAllUnfusedAsync: async ({ withDataAndSignature = true } = {}): Promise< + PartialBlob[] + > => { + const partialBlobsInDB = await prisma.partialBlob.findMany({ + where: { fusedBlobId: null }, + }); + const partialBlobs = partialBlobsInDB.map( convertPartialBlobInDBToPartialBlob, ); @@ -54,16 +65,10 @@ export const partialBlobRepository = { ...partialBlob, data: null, signature: null, + size: getLengthWithExtraBytes(partialBlob.data), })); }, - findAllUnfusedAsync: async (): Promise => { - const partialBlobsInDB = await prisma.partialBlob.findMany({ - where: { fusedBlobId: null }, - }); - return partialBlobsInDB.map(convertPartialBlobInDBToPartialBlob); - }, - findByIdAsync: async (id: number): Promise => { const partialBlobInDB = await prisma.partialBlob.findUnique({ where: { id }, diff --git a/src/blob-fuser/index.ts b/src/blob-fuser/index.ts index 25d8b4a..f2e758c 100644 --- a/src/blob-fuser/index.ts +++ b/src/blob-fuser/index.ts @@ -60,9 +60,20 @@ export const unfuseFusedBlob = (fusedBlob: Hex) => { return partialBlobs; }; -export const getDataLengthInHex = (data: Hex) => { +export const getLengthWithExtraBytes = (data: Hex) => { + return ( + SIGNATURE_LENGTH_IN_BYTES + + BLOB_DATA_SIZE_LENGTH_IN_BYTES + + getDataLength(data) + ); +}; + +export const getDataLength = (data: Hex) => { const bytes = toBytes(data); - const dataLength = bytes.length; + return bytes.length; +}; +export const getDataLengthInHex = (data: Hex) => { + const dataLength = getDataLength(data); return pad(toHex(dataLength), { size: BLOB_DATA_SIZE_LENGTH_IN_BYTES, });