Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetching block details from database #58

Merged
merged 5 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions prisma/schema.prisma
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please only commit the renaming of POSTGRES_URL to DATABASE_URL but keep the default option to use sqlite.

Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ generator client {
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
// provider = "postgres"
// url = env("POSTGRES_URL")
// provider = "postgres"
// url = env("DATABASE_URL")
}

model DeployConfig {
Expand Down
16 changes: 11 additions & 5 deletions src/app/contract/[hash]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from "react";
import { Card, CardContent } from "@/components/ui/card";
import DescriptionListItem from "@/components/lib/description-list-item";
import ContractValidator from "@/components/pages/contract/contract-validator";
Expand All @@ -13,9 +13,11 @@ type ContractStatus = {
async function getStatusForContract(hash: string): Promise<ContractStatus[]> {
const chainId = "11155420"; // op sepolia
const url = `https://sourcify.dev/server/check-by-addresses?addresses=${hash}&chainIds=${chainId}`;
const response = await fetch(url, { cache: 'no-store' });
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) {
throw new Error(`Failed to fetch status for contract: ${response.statusText}`);
throw new Error(
`Failed to fetch status for contract: ${response.statusText}`,
);
}
return response.json();
}
Expand All @@ -40,8 +42,12 @@ const ContractPage = async ({ params }: ContractPageProps) => {
<Card>
<CardContent className="p-4">
<dl>
<DescriptionListItem title="Contract Hash">{hash}</DescriptionListItem>
<DescriptionListItem title="Status">{statusData[0].status}</DescriptionListItem>
<DescriptionListItem title="Contract Hash">
{hash}
</DescriptionListItem>
<DescriptionListItem title="Status">
{statusData[0].status}
</DescriptionListItem>
</dl>
</CardContent>
</Card>
Expand Down
25 changes: 0 additions & 25 deletions src/components/lib/fetch-data.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a leftover and is no longer needed, please delete it.

This file was deleted.

32 changes: 32 additions & 0 deletions src/components/pages/block/fetch-block-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { l2PublicClient } from "@/lib/chains";
import { Block, fromViemBlock, fromPrismaBlock } from "@/lib/types";
import { prisma } from "@/lib/prisma";

const fetchBlockDetailsFromDatabase = async (
number: bigint
): Promise<Block | null> => {
const block = await prisma.block.findUnique({
where: { number },
include: { transactions: true },
});

if (!block) {
return fetchBlockDetailsFromJsonRpc(number);
}

return fromPrismaBlock(block, block.transactions);
};

const fetchBlockDetailsFromJsonRpc = async (
number: bigint
): Promise<Block | null> => {
const block = await l2PublicClient.getBlock({ blockNumber: number });

return block ? fromViemBlock(block) : null;
};

const fetchBlockDetails = process.env.DATABASE_URL
? fetchBlockDetailsFromDatabase
: fetchBlockDetailsFromJsonRpc;

export default fetchBlockDetails;
9 changes: 5 additions & 4 deletions src/components/pages/block/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { notFound } from "next/navigation";
import { l2PublicClient } from "@/lib/chains";
import { Card, CardContent } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import BlockDetails from "@/components/pages/block/block-details";
import { fromViemBlock } from "@/lib/types";
import fetchBlockDetails from "@/components/pages/block/fetch-block-details";

const Block = async ({ number }: { number: bigint }) => {
const block = await l2PublicClient.getBlock({ blockNumber: number });
const { block } = await fetchBlockDetails(number);

if (!block) {
notFound();
}

return (
<main className="flex flex-1 flex-col gap-4 p-4 md:gap-4 md:p-4">
<h2 className="flex items-center text-2xl font-bold tracking-tight">
Expand All @@ -21,7 +22,7 @@ const Block = async ({ number }: { number: bigint }) => {
<Separator />
<Card>
<CardContent className="p-4">
<BlockDetails block={fromViemBlock(block)} />
<BlockDetails block={block} />
</CardContent>
</Card>
</main>
Expand Down
57 changes: 34 additions & 23 deletions src/components/pages/contract/contract-validator.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import React, { useState, useEffect, ChangeEvent } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { solarizedlight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import React, { useState, useEffect, ChangeEvent } from "react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { solarizedlight } from "react-syntax-highlighter/dist/cjs/styles/prism";

type ContractFile = {
name: string;
Expand All @@ -27,9 +27,13 @@ const ContractValidator = ({ hash, initialStatus }: ContractValidatorProps) => {
const fetchFiles = async () => {
if (status === "perfect") {
try {
const response = await fetch(`https://sourcify.dev/server/files/${chainId}/${hash}`);
const response = await fetch(
`https://sourcify.dev/server/files/${chainId}/${hash}`,
);
if (!response.ok) {
throw new Error(`Failed to fetch files for contract: ${response.statusText}`);
throw new Error(
`Failed to fetch files for contract: ${response.statusText}`,
);
}
const filesData: ContractFile[] = await response.json();
setFiles(filesData);
Expand Down Expand Up @@ -59,15 +63,15 @@ const ContractValidator = ({ hash, initialStatus }: ContractValidatorProps) => {
address: hash,
chain: chainId,
files: {
"metadata.json": metadataContent
}
"metadata.json": metadataContent,
},
};
const response = await fetch('https://sourcify.dev/server/verify', {
method: 'POST',
const response = await fetch("https://sourcify.dev/server/verify", {
method: "POST",
headers: {
'Content-Type': 'application/json'
"Content-Type": "application/json",
},
body: JSON.stringify(payload)
body: JSON.stringify(payload),
});

if (!response.ok) {
Expand All @@ -78,7 +82,9 @@ const ContractValidator = ({ hash, initialStatus }: ContractValidatorProps) => {
const validationResult = result.result[0]; // Extract the first result item
setStatus(validationResult.status);
if (validationResult.status === "perfect") {
const filesResponse = await fetch(`https://sourcify.dev/server/files/${chainId}/${hash}`);
const filesResponse = await fetch(
`https://sourcify.dev/server/files/${chainId}/${hash}`,
);
const filesData: ContractFile[] = await filesResponse.json();
setFiles(filesData);
}
Expand All @@ -93,26 +99,31 @@ const ContractValidator = ({ hash, initialStatus }: ContractValidatorProps) => {
<div>
{status !== "perfect" && (
<div className="mt-4">
<h3 className="text-xl font-bold">Upload metadata.json to validate contract</h3>
<h3 className="text-xl font-bold">
Upload metadata.json to validate contract
</h3>
<input type="file" accept=".json" onChange={handleFileChange} />
<button onClick={handleSubmit} className="btn btn-primary mt-2">Submit</button>
<button onClick={handleSubmit} className="btn btn-primary mt-2">
Submit
</button>
</div>
)}

{isLoading && (
<div className="flex justify-center items-center mt-4">
<div className="mt-4 flex items-center justify-center">
<p>Validating contract, please wait...</p>
</div>
)}

{status === "perfect" && files.map((file, index) => (
<div key={index} className="mt-4">
<h3 className="text-xl font-bold">{file.name}</h3>
<SyntaxHighlighter language="solidity" style={solarizedlight}>
{file.content}
</SyntaxHighlighter>
</div>
))}
{status === "perfect" &&
files.map((file, index) => (
<div key={index} className="mt-4">
<h3 className="text-xl font-bold">{file.name}</h3>
<SyntaxHighlighter language="solidity" style={solarizedlight}>
{file.content}
</SyntaxHighlighter>
</div>
))}

{error && (
<div className="mt-4 text-red-500">
Expand Down
16 changes: 8 additions & 8 deletions src/components/ui/progress.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use client"
"use client";

import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"
import * as React from "react";
import * as ProgressPrimitive from "@radix-ui/react-progress";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
Expand All @@ -13,7 +13,7 @@ const Progress = React.forwardRef<
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className
className,
)}
{...props}
>
Expand All @@ -22,7 +22,7 @@ const Progress = React.forwardRef<
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName
));
Progress.displayName = ProgressPrimitive.Root.displayName;

export { Progress }
export { Progress };
20 changes: 10 additions & 10 deletions src/components/ui/separator.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
"use client"
"use client";

import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"
import * as React from "react";
import * as SeparatorPrimitive from "@radix-ui/react-separator";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{ className, orientation = "horizontal", decorative = true, ...props },
ref
ref,
) => (
<SeparatorPrimitive.Root
ref={ref}
Expand All @@ -20,12 +20,12 @@ const Separator = React.forwardRef<
className={cn(
"shrink-0 bg-border",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
className
className,
)}
{...props}
/>
)
)
Separator.displayName = SeparatorPrimitive.Root.displayName
),
);
Separator.displayName = SeparatorPrimitive.Root.displayName;

export { Separator }
export { Separator };
30 changes: 15 additions & 15 deletions src/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use client"
"use client";

import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import * as React from "react";
import * as TabsPrimitive from "@radix-ui/react-tabs";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const Tabs = TabsPrimitive.Root
const Tabs = TabsPrimitive.Root;

const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
Expand All @@ -15,12 +15,12 @@ const TabsList = React.forwardRef<
ref={ref}
className={cn(
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
className
className,
)}
{...props}
/>
))
TabsList.displayName = TabsPrimitive.List.displayName
));
TabsList.displayName = TabsPrimitive.List.displayName;

const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
Expand All @@ -30,12 +30,12 @@ const TabsTrigger = React.forwardRef<
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
className
className,
)}
{...props}
/>
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
));
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;

const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
Expand All @@ -45,11 +45,11 @@ const TabsContent = React.forwardRef<
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
className,
)}
{...props}
/>
))
TabsContent.displayName = TabsPrimitive.Content.displayName
));
TabsContent.displayName = TabsPrimitive.Content.displayName;

export { Tabs, TabsList, TabsTrigger, TabsContent }
export { Tabs, TabsList, TabsTrigger, TabsContent };
Loading