diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableContainer.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableContainer.tsx
index 44c5d8bad4..9592756567 100644
--- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableContainer.tsx
+++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableContainer.tsx
@@ -28,7 +28,7 @@ export type WatchedTransaction = {
transaction?: Transaction;
functionData?: DecodeFunctionDataReturnType;
receipt?: TransactionReceipt;
- status: "pending" | "success" | "reverted";
+ status: "pending" | "success" | "reverted" | "unknown";
write?: Write;
logs?: Log[];
error?: BaseError;
@@ -80,16 +80,6 @@ export function TransactionsTableContainer() {
const transaction = await getTransaction(wagmiConfig, { hash });
if (transaction.to !== worldAddress) return;
- setTransactions((prevTransactions) => [
- {
- hash,
- timestamp,
- transaction,
- status: "pending",
- },
- ...prevTransactions,
- ]);
-
let functionName: string | undefined;
let args: readonly unknown[] | undefined;
let transactionError: BaseError | undefined;
@@ -103,22 +93,42 @@ export function TransactionsTableContainer() {
functionName = transaction.input.length > 10 ? transaction.input.slice(0, 10) : "unknown";
}
- setTransactions((prevTransactions) =>
- prevTransactions.map((transaction) =>
- transaction.hash === hash
- ? {
- ...transaction,
- functionData: {
- functionName,
- args,
- },
- }
- : transaction,
- ),
- );
+ setTransactions((prevTransactions) => [
+ {
+ hash,
+ timestamp,
+ transaction,
+ status: "pending",
+ functionData: {
+ functionName,
+ args,
+ },
+ },
+ ...prevTransactions,
+ ]);
+
+ // Receipt
+ const maxRetries = 10;
+ const retryInterval = 2000;
+ let receipt: TransactionReceipt | undefined;
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
+ try {
+ receipt = await getTransactionReceipt(wagmiConfig, { hash });
+ if (receipt) break;
+ } catch (error) {
+ console.error(`Failed to fetch receipt, attempt ${attempt + 1}:`, error);
+ }
+
+ if (attempt < maxRetries - 1) {
+ await new Promise((resolve) => setTimeout(resolve, retryInterval));
+ }
+ }
+
+ if (!receipt) {
+ console.error(`Failed to fetch transaction receipt after ${maxRetries} attempts`);
+ }
- const receipt = await getTransactionReceipt(wagmiConfig, { hash });
- if (receipt.status === "reverted" && functionName) {
+ if (receipt && receipt.status === "reverted" && functionName) {
try {
// Simulate the failed transaction to retrieve the revert reason
// Note, it only works for functions that are declared in the ABI
@@ -137,9 +147,10 @@ export function TransactionsTableContainer() {
}
}
+ const status = receipt ? receipt.status : "unknown";
const logs = parseEventLogs({
abi,
- logs: receipt.logs,
+ logs: receipt?.logs || [],
});
setTransactions((prevTransactions) =>
@@ -149,7 +160,7 @@ export function TransactionsTableContainer() {
...transaction,
receipt,
logs,
- status: receipt.status,
+ status,
error: transactionError,
}
: transaction,
@@ -159,6 +170,18 @@ export function TransactionsTableContainer() {
[abi, wagmiConfig, worldAddress],
);
+ useEffect(() => {
+ for (const write of observerWrites) {
+ const hash = write.hash;
+ if (write.type === "waitForTransactionReceipt" && hash) {
+ const transaction = transactions.find((transaction) => transaction.hash === hash);
+ if (!transaction) {
+ handleTransaction(hash, BigInt(write.time) / 1000n);
+ }
+ }
+ }
+ }, [handleTransaction, observerWrites, transactions]);
+
useWatchBlocks({
onBlock(block) {
for (const hash of block.transactions) {
@@ -170,22 +193,5 @@ export function TransactionsTableContainer() {
pollingInterval: 500,
});
- useEffect(() => {
- const handleVisibilityChange = () => {
- if (!document.hidden) {
- for (const write of observerWrites) {
- if (write.hash && !transactions.find((t) => t.hash === write.hash)) {
- handleTransaction(write.hash, BigInt(write.time) / 1000n);
- }
- }
- }
- };
-
- document.addEventListener("visibilitychange", handleVisibilityChange);
- return () => {
- document.removeEventListener("visibilitychange", handleVisibilityChange);
- };
- }, [handleTransaction, observerWrites, transactions]);
-
return ;
}
diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableView.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableView.tsx
index 62975e804d..d93a3b9d3a 100644
--- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableView.tsx
+++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTableView.tsx
@@ -13,7 +13,7 @@ import { WatchedTransaction } from "./TransactionsTableContainer";
const columnHelper = createColumnHelper();
export const columns = [
- columnHelper.accessor("transaction.blockNumber", {
+ columnHelper.accessor("receipt.blockNumber", {
header: "Block",
cell: (row) => {
const blockNumber = row.getValue();
diff --git a/packages/explorer/src/observer/store.ts b/packages/explorer/src/observer/store.ts
index 0eae89719d..5c4e78b414 100644
--- a/packages/explorer/src/observer/store.ts
+++ b/packages/explorer/src/observer/store.ts
@@ -8,6 +8,7 @@ import { Message, MessageType } from "./messages";
export type Write = {
writeId: string;
+ type: MessageType;
hash?: Hex;
address: Address;
functionSignature: string;
@@ -37,6 +38,7 @@ channel.addEventListener("message", ({ data }: MessageEvent) => {
...state.writes,
[data.writeId]: {
...write,
+ type: data.type,
hash: data.type === "waitForTransactionReceipt" ? data.hash : write.hash,
events: [...write.events, data],
},