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

feat: adding transactions page and transaction details page #42

Merged
merged 4 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { KeyValueDisplay } from "./key-value-display";

interface InfoDisplayProps {
blockData: {
key: string;
label: string;
value: string;
isClickable?: boolean;
}[];
}

const InfoDisplay: FC<InfoDisplayProps> = ({ blockData }) => {
export const InfoDisplay: FC<InfoDisplayProps> = ({ blockData }) => {
return (
<div className="p-4">
<KeyValueDisplay data={blockData} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import { FC } from "react";
import { KeyValueRow } from "./key-value-row";

interface DetailItem {
label: string;
value: string;
isClickable?: boolean;
}

interface KeyValueDisplayProps {
data: {
key: string;
value: string;
}[];
data: DetailItem[];
}

export const KeyValueDisplay: FC<KeyValueDisplayProps> = ({ data }) => (
<div className="bg-white rounded-lg shadow-md p-4">
<>
{data.map((item, index) => (
<KeyValueRow
key={index}
label={item.key}
label={item.label}
value={item.value}
isLast={index === data.length - 1}
isClickable={item.isClickable}
/>
))}
</div>
</>
);
17 changes: 15 additions & 2 deletions services/explorer-ui/src/components/info-display/key-value-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,29 @@ import { FC } from "react";
interface KeyValueRowProps {
label: string;
value: string;
isClickable?: boolean;
isLast?: boolean;
}

export const KeyValueRow: FC<KeyValueRowProps> = ({ label, value, isLast }) => (
export const KeyValueRow: FC<KeyValueRowProps> = ({
label,
value,
isLast,
isClickable = false,
}) => (
<div
className={`flex items-center py-3 ${
!isLast ? "border-b border-gray-200" : ""
}`}
>
<span className="text-gray-600 w-1/5">{label}</span>
<span className="font-medium text-right">{value}</span>
<span
className={`text-sm flex-grow ${
isClickable ? "text-blue-600 cursor-pointer" : ""
}`}
>
{value}
{isClickable && <span className="ml-1">🔗</span>}
</span>
</div>
);
63 changes: 44 additions & 19 deletions services/explorer-ui/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@ import { Route as rootRoute } from './routes/__root'

// Create Virtual Routes

const TransactionsLazyImport = createFileRoute('/transactions')()
const ContractsLazyImport = createFileRoute('/contracts')()
const IndexLazyImport = createFileRoute('/')()
const TransactionsIndexLazyImport = createFileRoute('/transactions/')()
const BlocksIndexLazyImport = createFileRoute('/blocks/')()
const TransactionsTransactionIdLazyImport = createFileRoute(
'/transactions/$transactionId',
)()
const BlocksBlockNumberLazyImport = createFileRoute('/blocks/$blockNumber')()

// Create/Update Routes

const TransactionsLazyRoute = TransactionsLazyImport.update({
path: '/transactions',
getParentRoute: () => rootRoute,
} as any).lazy(() => import('./routes/transactions.lazy').then((d) => d.Route))

const ContractsLazyRoute = ContractsLazyImport.update({
path: '/contracts',
getParentRoute: () => rootRoute,
Expand All @@ -39,11 +37,26 @@ const IndexLazyRoute = IndexLazyImport.update({
getParentRoute: () => rootRoute,
} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route))

const TransactionsIndexLazyRoute = TransactionsIndexLazyImport.update({
path: '/transactions/',
getParentRoute: () => rootRoute,
} as any).lazy(() =>
import('./routes/transactions/index.lazy').then((d) => d.Route),
)

const BlocksIndexLazyRoute = BlocksIndexLazyImport.update({
path: '/blocks/',
getParentRoute: () => rootRoute,
} as any).lazy(() => import('./routes/blocks/index.lazy').then((d) => d.Route))

const TransactionsTransactionIdLazyRoute =
TransactionsTransactionIdLazyImport.update({
path: '/transactions/$transactionId',
getParentRoute: () => rootRoute,
} as any).lazy(() =>
import('./routes/transactions/$transactionId.lazy').then((d) => d.Route),
)

const BlocksBlockNumberLazyRoute = BlocksBlockNumberLazyImport.update({
path: '/blocks/$blockNumber',
getParentRoute: () => rootRoute,
Expand All @@ -69,27 +82,34 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ContractsLazyImport
parentRoute: typeof rootRoute
}
'/transactions': {
id: '/transactions'
path: '/transactions'
fullPath: '/transactions'
preLoaderRoute: typeof TransactionsLazyImport
parentRoute: typeof rootRoute
}
'/blocks/$blockNumber': {
id: '/blocks/$blockNumber'
path: '/blocks/$blockNumber'
fullPath: '/blocks/$blockNumber'
preLoaderRoute: typeof BlocksBlockNumberLazyImport
parentRoute: typeof rootRoute
}
'/transactions/$transactionId': {
id: '/transactions/$transactionId'
path: '/transactions/$transactionId'
fullPath: '/transactions/$transactionId'
preLoaderRoute: typeof TransactionsTransactionIdLazyImport
parentRoute: typeof rootRoute
}
'/blocks/': {
id: '/blocks/'
path: '/blocks'
fullPath: '/blocks'
preLoaderRoute: typeof BlocksIndexLazyImport
parentRoute: typeof rootRoute
}
'/transactions/': {
id: '/transactions/'
path: '/transactions'
fullPath: '/transactions'
preLoaderRoute: typeof TransactionsIndexLazyImport
parentRoute: typeof rootRoute
}
}
}

Expand All @@ -98,9 +118,10 @@ declare module '@tanstack/react-router' {
export const routeTree = rootRoute.addChildren({
IndexLazyRoute,
ContractsLazyRoute,
TransactionsLazyRoute,
BlocksBlockNumberLazyRoute,
TransactionsTransactionIdLazyRoute,
BlocksIndexLazyRoute,
TransactionsIndexLazyRoute,
})

/* prettier-ignore-end */
Expand All @@ -113,9 +134,10 @@ export const routeTree = rootRoute.addChildren({
"children": [
"/",
"/contracts",
"/transactions",
"/blocks/$blockNumber",
"/blocks/"
"/transactions/$transactionId",
"/blocks/",
"/transactions/"
]
},
"/": {
Expand All @@ -124,14 +146,17 @@ export const routeTree = rootRoute.addChildren({
"/contracts": {
"filePath": "contracts.lazy.tsx"
},
"/transactions": {
"filePath": "transactions.lazy.tsx"
},
"/blocks/$blockNumber": {
"filePath": "blocks/$blockNumber.lazy.tsx"
},
"/transactions/$transactionId": {
"filePath": "transactions/$transactionId.lazy.tsx"
},
"/blocks/": {
"filePath": "blocks/index.lazy.tsx"
},
"/transactions/": {
"filePath": "transactions/index.lazy.tsx"
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions services/explorer-ui/src/routes/blocks/$blockNumber.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ export const Route = createLazyFileRoute("/blocks/$blockNumber")({
});

const blockData = [
{ key: "BLOCK NUMBER", value: "348540" },
{ label: "BLOCK NUMBER", value: "348540" },
{
key: "BLOCK HASH",
label: "BLOCK HASH",
value:
"0x995542b01a706c56d3a962ba819e765ree057egtr4311562cdf6286147fbf9cf51",
},
{ key: "STATUS", value: "FINALISED" },
{ key: "TIMESTAMP", value: "1 min ago (Jun-07-2024 08:47:23 AM UTC)" },
{ key: "TRANSACTIONS", value: "155 transactions" },
{ key: "TOTAL FEES", value: "0.000122453 ETH ($0.05)" },
{ key: "SIZE", value: "46,377 bytes" },
{ key: "LOGS", value: "323 logs" },
{ label: "STATUS", value: "FINALISED" },
{ label: "TIMESTAMP", value: "1 min ago (Jun-07-2024 08:47:23 AM UTC)" },
{ label: "TRANSACTIONS", value: "155 transactions" },
{ label: "TOTAL FEES", value: "0.000122453 ETH ($0.05)" },
{ label: "SIZE", value: "46,377 bytes" },
{ label: "LOGS", value: "323 logs" },
{
key: "PARENT HASH",
label: "PARENT HASH",
value: "0xebe7fuy7655b6506fe587hj7c2ad1237b242b9adc60ci8u7y972728ce63b526b",
},
];
Expand Down Expand Up @@ -92,7 +92,7 @@ function Block() {
<p>{bn}</p>
</div>
<div className="flex flex-col gap-4 mt-8">
<div className="">
<div className="bg-white rounded-lg shadow-md p-4">
<KeyValueDisplay data={blockData} />
</div>
<div className="flex flex-row gap-4 w-10 mb-4">
Expand Down
17 changes: 0 additions & 17 deletions services/explorer-ui/src/routes/transactions.lazy.tsx

This file was deleted.

106 changes: 106 additions & 0 deletions services/explorer-ui/src/routes/transactions/$transactionId.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import { FC, useState } from "react";
import { KeyValueDisplay } from "~/components/info-display/key-value-display";
import { Button } from "~/components/ui";

export const Route = createLazyFileRoute("/transactions/$transactionId")({
component: TransactionDetails,
});

const transactionData = [
{
label: "HASH",
value: "0xb950b8ba84a4f35f85d5f62a0e3f8b161d8733479c14d426dc36ae30f7e96246",
isClickable: true,
},
{ label: "STATUS", value: "SUCCESS" },
{
label: "BLOCK NUMBER",
value: "348540 (confirmed by sequencer)",
isClickable: true,
},
{ label: "TIMESTAMP", value: "1 min ago (Jun-07-2024 08:47:23 AM UTC)" },
{
label: "L1 BATCH TX",
value: "0xb950b8ba84a4f35f85d5f62a0e3f8b161d8733479c14d426dc36ae30f7e92341",
isClickable: true,
},
{ label: "TRANSACTION FEE", value: "0.000012245344159887766 ETH ($0.05)" },
];

const feeData = [
{ label: "TRANSACTION FEE", value: "0.000012453 ETH" },
{ label: "FPA USED", value: "ETHER" },
{ label: "GAS PRICE", value: "0.000012453 ETH" },
{ label: "GAS", value: "0.000012453 ETH" },
{ label: "FEE USED FOR L2 GAS", value: "0.000012453 ETH" },
{ label: "L1 GAS", value: "0.000012453 ETH" },
{ label: "DATA AVAILABILITY FEE", value: "0.000012453 ETH" },
{ label: "COINBASE", value: "0.000012453 ETH" },
{
label: "FEE RECIPIENT",
value: "0xb950b8ba84a4f35f85d5f62a0e3f8b161d8733479c14d426dc36ae30f7e96246",
isClickable: true,
},
];

function TransactionDetails() {
const [selectedButton, setSelectedButton] = useState("transactionEffects");
const { transactionId } = Route.useParams();

return (
<div className="mx-auto px-[70px] max-w-[1440px]">
{transactionId ? (
<div>
<div>
<h2>Transaction details</h2>
<p>{transactionId}</p>
</div>
<div className="flex flex-col gap-4 mt-8">
<div className="bg-white rounded-lg shadow-md p-4">
<KeyValueDisplay data={transactionData} />
</div>
<div className="flex flex-row gap-4 w-10 mb-4">
<Button
variant={"primary"}
onClick={() => setSelectedButton("transactionEffects")}
>
Transaction effects
</Button>
<Button
variant={"primary"}
onClick={() => setSelectedButton("feeDetails")}
>
View Transactions
</Button>
</div>
{selectedButton === "transactionEffects" && (
<div className="bg-white rounded-lg shadow-md p-4">
<h3>Transaction Effects</h3>
</div>
)}
{selectedButton === "feeDetails" && (
<div className="bg-white rounded-lg shadow-md p-4">
<div className="flex flex-col mt-8">
<h3>Fee Details</h3>
<KeyValueDisplay data={feeData} />
</div>
<div className="flex flex-col mt-8">
<h3>Public fee Details</h3>
<KeyValueDisplay data={feeData} />
</div>
</div>
)}
</div>
</div>
) : (
//TODO: create reusable component
<div>
<h2>Invalid Transaction Id</h2>
<p>transaction {transactionId} not found</p>
</div>
)}
</div>
);
}

Loading