Skip to content

Commit

Permalink
handle incoming txs from observer, retry receipt fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
karooolis committed Oct 3, 2024
1 parent 0cc0c5f commit e6afd91
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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) =>
Expand All @@ -149,7 +160,7 @@ export function TransactionsTableContainer() {
...transaction,
receipt,
logs,
status: receipt.status,
status,
error: transactionError,
}
: transaction,
Expand All @@ -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) {
Expand All @@ -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 <TransactionsTableView data={mergedTransactions} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { WatchedTransaction } from "./TransactionsTableContainer";

const columnHelper = createColumnHelper<WatchedTransaction>();
export const columns = [
columnHelper.accessor("transaction.blockNumber", {
columnHelper.accessor("receipt.blockNumber", {
header: "Block",
cell: (row) => {
const blockNumber = row.getValue();
Expand Down
2 changes: 2 additions & 0 deletions packages/explorer/src/observer/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Message, MessageType } from "./messages";

export type Write = {
writeId: string;
type: MessageType;
hash?: Hex;
address: Address;
functionSignature: string;
Expand Down Expand Up @@ -37,6 +38,7 @@ channel.addEventListener("message", ({ data }: MessageEvent<Message>) => {
...state.writes,
[data.writeId]: {
...write,
type: data.type,
hash: data.type === "waitForTransactionReceipt" ? data.hash : write.hash,
events: [...write.events, data],
},
Expand Down

0 comments on commit e6afd91

Please sign in to comment.