Skip to content

Commit 53bdb13

Browse files
committed
fetch latest blocks from shovel api
1 parent 5d17a25 commit 53bdb13

3 files changed

Lines changed: 66 additions & 8 deletions

File tree

packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsWatcher.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Address,
44
BaseError,
55
Hash,
6+
Hex,
67
Transaction,
78
TransactionReceipt,
89
decodeFunctionData,
@@ -17,17 +18,21 @@ import { useStore } from "zustand";
1718
import { useCallback, useEffect } from "react";
1819
import { store as observerStore } from "../../../../../../observer/store";
1920
import { useChain } from "../../../../hooks/useChain";
21+
import { useBlocksQuery } from "../../../../queries/useBlocksQuery";
2022
import { useWorldAbiQuery } from "../../../../queries/useWorldAbiQuery";
23+
import { indexerForChainId } from "../../../../utils/indexerForChainId";
2124
import { store as worldStore } from "../store";
2225
import { userOperationEventAbi } from "./abis/userOperationEventAbi";
2326
import { getDecodedUserOperationCalls } from "./utils/getDecodedUserOperationCalls";
2427

2528
export function TransactionsWatcher() {
2629
const { id: chainId } = useChain();
2730
const { worldAddress } = useParams<{ worldAddress: Address }>();
31+
const indexer = indexerForChainId(chainId);
2832
const wagmiConfig = useConfig();
2933
const { data: worldAbiData } = useWorldAbiQuery();
3034
const abi = worldAbiData?.abi;
35+
const { data: blocks } = useBlocksQuery();
3136
const { transactions, setTransaction, updateTransaction } = useStore(worldStore);
3237
const observerWrites = useStore(observerStore, (state) => state.writes);
3338

@@ -217,6 +222,23 @@ export function TransactionsWatcher() {
217222
}
218223
}, [handleTransaction, observerWrites, transactions, worldAddress]);
219224

225+
useEffect(() => {
226+
const handleBlock = async (blockHash: Hex, blockTime: bigint) => {
227+
const block = await getBlock(wagmiConfig, { chainId, blockHash });
228+
const blockTxs = block.transactions;
229+
for (const hash of blockTxs) {
230+
if (transactions.find((transaction) => transaction.hash === hash)) continue;
231+
handleTransaction({ hash, timestamp: blockTime });
232+
}
233+
};
234+
235+
if (blocks) {
236+
for (const { block_hash, block_time } of blocks) {
237+
handleBlock(`0x${block_hash}`, BigInt(block_time));
238+
}
239+
}
240+
}, [blocks, chainId, handleTransaction, transactions, wagmiConfig]);
241+
220242
useWatchBlocks({
221243
chainId,
222244
async onBlock(block) {
@@ -229,6 +251,7 @@ export function TransactionsWatcher() {
229251
handleTransaction({ hash, timestamp: block.timestamp });
230252
}
231253
},
254+
enabled: indexer.type === "sqlite",
232255
});
233256

234257
return null;

packages/explorer/src/app/(explorer)/api/transactions/route.ts renamed to packages/explorer/src/app/(explorer)/api/blocks/route.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Client } from "pg";
22
import { Hex } from "viem";
33

4+
export const dynamic = "force-dynamic";
5+
46
const postgresConnectionUrl = process.env.DATABASE_URL;
57

68
export async function GET(req: Request) {
@@ -9,23 +11,19 @@ export async function GET(req: Request) {
911
const worldAddress = searchParams.get("worldAddress") as Hex;
1012
const offset = Number(searchParams.get("offset")) || 0;
1113
const limit = Number(searchParams.get("limit")) || 10;
12-
const columns = searchParams.get("columns") || "*";
1314

1415
if (!worldAddress) {
1516
return Response.json({ error: "Missing worldAddress" }, { status: 400 });
1617
}
1718

1819
try {
1920
await client.connect();
20-
21-
const transactions = await client.query(
22-
`SELECT ${columns} FROM transactions WHERE tx_to = decode($1, 'hex') ORDER BY block_num DESC OFFSET $2 LIMIT $3`,
23-
[worldAddress, offset, limit],
21+
const blocks = await client.query(
22+
`SELECT DISTINCT encode(block_hash, 'hex') as block_hash, block_num, block_time FROM transactions WHERE tx_to = decode($1, 'hex') ORDER BY block_num DESC OFFSET $2 LIMIT $3`,
23+
[worldAddress.replace("0x", ""), offset, limit],
2424
);
2525

26-
return Response.json({
27-
transactions: transactions.rows,
28-
});
26+
return Response.json({ blocks: blocks.rows });
2927
} catch (error) {
3028
console.error("Database error:", error);
3129
return Response.json({ error: "Failed to fetch transactions" }, { status: 500 });
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useParams } from "next/navigation";
2+
import { Hex } from "viem";
3+
import { useQuery } from "@tanstack/react-query";
4+
import { useChain } from "../hooks/useChain";
5+
import { indexerForChainId } from "../utils/indexerForChainId";
6+
7+
export function useBlocksQuery() {
8+
const { worldAddress, chainName } = useParams();
9+
const { id: chainId } = useChain();
10+
const indexer = indexerForChainId(chainId);
11+
12+
return useQuery({
13+
queryKey: ["blocks", worldAddress, chainName],
14+
queryFn: async () => {
15+
const offset = 0;
16+
const limit = 10;
17+
const response = await fetch(
18+
`/api/blocks?${new URLSearchParams({
19+
worldAddress: worldAddress as Hex,
20+
offset: offset.toString(),
21+
limit: limit.toString(),
22+
})}`,
23+
{
24+
method: "GET",
25+
},
26+
);
27+
28+
return response.json();
29+
},
30+
select: (data) => {
31+
return data.blocks;
32+
},
33+
retry: false,
34+
enabled: !!worldAddress && indexer.type === "hosted",
35+
refetchInterval: 2000,
36+
});
37+
}

0 commit comments

Comments
 (0)