Skip to content

Commit

Permalink
feat: update L1 origin block hash handling and add full L1 origin blo…
Browse files Browse the repository at this point in the history
…ck hash field (#631)

* feat: update L1 origin block hash handling and add full L1 origin block hash field

* fix(api): prepend "0x" to partial hash in autocompleteBlockHash function

* feat(api): move autocompleteBlockHash function to optimism.ts and remove old file

* refactor(api): remove export from autocompleteBlockHash function in optimism.ts

* feat(tx): create BlockHash component for L1 origin block hash display

* chore: added changeset

* fix: update label to tooltipText for CopyToClipboard component

* fix: handle empty partialHash in autocompleteBlockHash function and improve logging for multiple block occurrences
  • Loading branch information
luis-herasme authored Dec 2, 2024
1 parent 394873a commit d5ef1bc
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 52 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-beans-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/web": patch
---

Added a link to the L1 origin block if the full hash is found using the optimism decoded fields.
51 changes: 31 additions & 20 deletions apps/web/src/pages/tx/[hash].tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { FC } from "react";
import { useMemo } from "react";
import type { NextPage } from "next";
import { useRouter } from "next/router";
Expand Down Expand Up @@ -280,30 +281,15 @@ const Tx: NextPage = () => {
},
{
name: "Parent L2 block hash",
value: (
<div className="flex items-center gap-2">
{"0x" + decodedData.parentL2BlockHash + "..."}
</div>
),
value: "0x" + decodedData.parentL2BlockHash + "...",
},
{
name: "L1 origin block hash",
value: (
<div className="flex items-center gap-2">
<Link
href={
"https://etherscan.io/block/" +
"0x" +
decodedData.l1OriginBlockHash
}
>
{"0x" + decodedData.l1OriginBlockHash}
</Link>
<CopyToClipboard
value={"0x" + decodedData.l1OriginBlockHash}
tooltipText="Copy L1 origin block hash"
/>
</div>
<BlockHash
fullHash={decodedData.fullL1OriginBlockHash}
partialHash={decodedData.l1OriginBlockHash}
/>
),
},
{
Expand Down Expand Up @@ -339,4 +325,29 @@ const Tx: NextPage = () => {
);
};

type BlockHashProps = {
partialHash: string;
fullHash: string | undefined;
};

const BlockHash: FC<BlockHashProps> = ({ fullHash, partialHash }) => {
if (fullHash === undefined) {
return "0x" + partialHash + "...";
}

const prefixedFullHash = "0x" + fullHash;

return (
<div className="flex items-center gap-2">
<Link href={`https://blobscan.com/block/${prefixedFullHash}`}>
{prefixedFullHash}
</Link>
<CopyToClipboard
value={prefixedFullHash}
tooltipText="Copy L1 origin block hash"
/>
</div>
);
};

export default Tx;
39 changes: 36 additions & 3 deletions packages/api/src/blob-parse/optimism.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { z } from "zod";

import { prisma } from "@blobscan/db";
import { logger } from "@blobscan/logger";

import { autocompleteBlockHash } from "../utils/autocompleteBlockHash";

export const OptimismDecodedDataSchema = z.object({
timestampSinceL2Genesis: z.number(),
lastL1OriginNumber: z.number(),
Expand All @@ -13,6 +12,7 @@ export const OptimismDecodedDataSchema = z.object({
changedByL1Origin: z.number(),
totalTxs: z.number(),
contractCreationTxsNumber: z.number(),
fullL1OriginBlockHash: z.string().optional(),
});

type OptimismDecodedData = z.infer<typeof OptimismDecodedDataSchema>;
Expand All @@ -37,7 +37,7 @@ export async function parseOptimismDecodedData(
const hash = await autocompleteBlockHash(decoded.data.l1OriginBlockHash);

if (hash) {
decoded.data.l1OriginBlockHash = hash;
decoded.data.fullL1OriginBlockHash = hash;
} else {
logger.error(
`Failed to get full block hash for L1 origin block hash: ${decoded.data.l1OriginBlockHash}`
Expand All @@ -46,3 +46,36 @@ export async function parseOptimismDecodedData(

return decoded.data;
}

/* Autocomplete a block hash from a truncated version of it.
@param partialHash - The first bytes of a block hash.
@returns The block hash, if there is a single ocurrence, or null.
*/
async function autocompleteBlockHash(partialHash: string) {
if (!partialHash) {
return null;
}

const blocks = await prisma.block.findMany({
where: {
hash: {
startsWith: "0x" + partialHash,
},
},
select: {
hash: true,
},
});

if (blocks[0] === undefined) {
return null;
}

if (blocks.length > 1) {
logger.error(
`Found ${blocks.length} blocks while autocompleting block hash ${partialHash}`
);
}

return blocks[0].hash;
}
29 changes: 0 additions & 29 deletions packages/api/src/utils/autocompleteBlockHash.ts

This file was deleted.

0 comments on commit d5ef1bc

Please sign in to comment.