Skip to content

Commit

Permalink
Merge pull request #69 from penumbra-zone/#6-update-blocks-page
Browse files Browse the repository at this point in the history
Updated Block Endpoint + Page to only include Block level ABCI events + associated transactions.
  • Loading branch information
ejmg authored Mar 11, 2024
2 parents c5b69ec + a9dd6fe commit 56469b5
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 82 deletions.
66 changes: 10 additions & 56 deletions src/app/api/block/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import db from "@/lib/db";
import { transactionFromBytes } from "@/lib/protobuf";
// import { transactionFromBytes } from "@/lib/protobuf";
import { BlockHeightValidator } from "@/lib/validators/search";
import { z } from "zod";

Expand All @@ -15,16 +15,17 @@ export async function GET(req: Request) {
// NOTE: This endpoint doesn't return the plain data of a single block. It finds the block by height and, if they exist, attaches any associated events and transaction results.
// Duplicate height event attributes are also filtered out.
console.log(`querying database for block with height ${ht}.`);
const query = await db.blocks.findFirstOrThrow({

const block = await db.blocks.findFirstOrThrow({
where: {
height: ht,
},
select: {
chain_id: true,
created_at: true,
height: true,
events: {
select: {
block_id: true,
type: true,
attributes: {
select: {
Expand All @@ -34,70 +35,23 @@ export async function GET(req: Request) {
},
},
where: {
AND: [
{
type: {
not: "block",
},
},
{
NOT: {
AND: [
{
type: "tx",
},
{
attributes: {
some: {
OR: [
{
key: {
equals: "height",
},
},
{
key: {
equals: "hash",
},
},
],
},
},
},
],
},
},
],
tx_id: {
equals: null,
},
},
},
tx_results: {
select: {
tx_hash: true,
tx_result: true,
},
},
},
});

console.log("Successfully queried block:", query);

const tx = query.tx_results.at(0);
const {tx_results : _, ...block} = query;
// eslint-disable-next-line @typescript-eslint/naming-convention
let tx_hash = "";
if (tx !== undefined) {
const penumbraTx = transactionFromBytes(tx.tx_result);
console.log("Successfully decoded Transaction from blockEvent.tx_results:", penumbraTx);

// eslint-disable-next-line @typescript-eslint/naming-convention
tx_hash = tx.tx_hash;
// BUG: Liable to throw the same `Error: ... cannot encode field penumbra.core.component.ibc.v1.IbcRelay.raw_action to JSON: cannot encode message google.protobuf.Any to JSON: "/ibc.core.client.v1.MsgCreateClient" is not in the type registry`
// error for transactions associated with an e.g. `update_client` event.
return new Response(JSON.stringify([{tx_hash, ...block}, penumbraTx.toJson()]));
}
console.log("Successfully queried block data: ", block, block.events);

console.log("No Transaction associated with block.");
return new Response(JSON.stringify([{tx_hash, ...block}, null]));
console.log("Serializing result...");
return new Response(JSON.stringify(block));
} catch (error) {
console.log(error);
if (error instanceof z.ZodError) {
Expand Down
11 changes: 5 additions & 6 deletions src/app/block/[ht]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { type FC } from "react";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { BlockResult } from "@/lib/validators/search";
import { BlockData } from "@/lib/validators/search";
import Block from "@/components/Block";

interface PageProps {
Expand All @@ -20,8 +20,7 @@ const Page : FC<PageProps> = ({ params }) => {
console.log(`Fetching: GET /api/block?q=${ht}`);
const { data } = await axios.get(`/api/block?q=${ht}`);
console.log("Fetching result:", data);
const result = BlockResult.safeParse(data);
console.log(result);
const result = BlockData.safeParse(data);
if (result.success) {
return result.data;
} else {
Expand Down Expand Up @@ -49,9 +48,9 @@ const Page : FC<PageProps> = ({ params }) => {
{isFetched ? (
<div>
{blockData ? (
<div className="flex flex-col justify-center w-full">
<h1 className="text-3xl mx-auto py-5 font-semibold">Block Summary</h1>
<Block blockPayload={blockData}/>
<div className="flex flex-col gap-5 pt-5 items-center">
<h1 className="sm:text-2xl font-bold">Block Summary</h1>
<Block blockData={blockData}/>
</div>
) : (
<div>
Expand Down
36 changes: 16 additions & 20 deletions src/lib/validators/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,26 +140,22 @@ export const TransactionResult = z.tuple([
]);

// zod schema equivalent to the /parsed/ JSON data returned by prisma in GET /api/block?q=<height>
// NOTE: This definition is meaningfully different from TransactionResult in that the Transaction value may not exist at all.
export const BlockResult = z.tuple([
z.object({
chain_id: z.string(),
created_at: z.string().datetime(),
height: z.coerce.bigint(),
events: z.array(z.object({
export const BlockData = z.object({
created_at: z.string().datetime(),
height: z.coerce.bigint(),
events: z.array(
z.object({
type: z.string(),
attributes: z.array(z.object({
value: z.string().nullable(),
key: z.string(),
})),
})),
tx_hash: z.string(),
}),
z.string().transform((jsonString) => {
const parsed = Transaction.fromJsonString(jsonString);
return parsed;
}).nullable(),
]);
attributes: z.array(
z.object({
value: z.string().nullable(),
key: z.string(),
}),
),
}),
),
tx_results: z.array(z.object({ tx_hash: z.string() })),
});

export type TransactionResultPayload = z.infer<typeof TransactionResult>;
export type BlockResultPayload = z.infer<typeof BlockResult>;
export type BlockDataPayload = z.infer<typeof BlockData>;

0 comments on commit 56469b5

Please sign in to comment.