Skip to content

Commit 07b6be8

Browse files
authored
feat(explorer): buffer transactions (#3365)
1 parent d542357 commit 07b6be8

File tree

3 files changed

+56
-29
lines changed

3 files changed

+56
-29
lines changed

.changeset/blue-trees-invent.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@latticexyz/explorer": patch
3+
---
4+
5+
The transactions list in the explorer is now updated every 100ms instead of on every incoming transaction, to improve performance when there are many incoming transactions.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
parseEventLogs,
1212
} from "viem";
1313
import { UserOperation, entryPoint07Abi, entryPoint07Address } from "viem/account-abstraction";
14+
import { anvil } from "viem/chains";
1415
import { useConfig, useWatchBlocks } from "wagmi";
1516
import { getTransaction, simulateContract, waitForTransactionReceipt } from "wagmi/actions";
1617
import { useStore } from "zustand";
@@ -225,7 +226,7 @@ export function TransactionsWatcher() {
225226
}
226227
},
227228
chainId,
228-
pollingInterval: 500,
229+
pollingInterval: chainId === anvil.id ? 10 : 500,
229230
});
230231

231232
return null;

packages/explorer/src/observer/store.ts

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,37 +31,58 @@ export const store = createStore<State>(() => ({
3131
}));
3232

3333
debug("listening for relayed messages", relayChannelName);
34+
const messageBuffer: MessageEvent<Message>[] = [];
3435
const channel = new BroadcastChannel(relayChannelName);
35-
channel.addEventListener("message", ({ data }: MessageEvent<Message>) => {
36-
if (data.type === "ping") return;
36+
37+
channel.addEventListener("message", (message: MessageEvent<Message>) => {
38+
if (message.data.type === "ping") return;
39+
messageBuffer.push(message);
40+
});
41+
42+
function flushMessageBuffer(): void {
43+
if (messageBuffer.length === 0) return;
44+
3745
store.setState((state) => {
38-
const write = data.type === "write" ? ({ ...data, events: [] } satisfies Write) : state.writes[data.writeId];
39-
if (!write) return state;
46+
let updated = state;
4047

41-
let hash = write.hash;
42-
if (data.type === "waitForTransactionReceipt") {
43-
hash = data.hash;
44-
} else if (
45-
data.type === "waitForUserOperationReceipt:result" &&
46-
isPromiseFulfilled<
47-
Messages["waitForUserOperationReceipt:result"] extends PromiseSettledResult<infer T> ? T : never
48-
>(data)
49-
) {
50-
hash = data.value.receipt.transactionHash;
51-
}
48+
for (const { data } of messageBuffer) {
49+
if (data.type === "ping") continue;
50+
51+
const write = data.type === "write" ? ({ ...data, events: [] } satisfies Write) : updated.writes[data.writeId];
52+
if (!write) continue;
5253

53-
return {
54-
...state,
55-
writes: {
56-
...state.writes,
57-
[data.writeId]: {
58-
...write,
59-
type: data.type,
60-
hash,
61-
userOpHash: data.type === "waitForUserOperationReceipt" ? data.userOpHash : write.userOpHash,
62-
events: [...write.events, data],
54+
let hash = write.hash;
55+
if (data.type === "waitForTransactionReceipt") {
56+
hash = data.hash;
57+
} else if (
58+
data.type === "waitForUserOperationReceipt:result" &&
59+
isPromiseFulfilled<
60+
Messages["waitForUserOperationReceipt:result"] extends PromiseSettledResult<infer T> ? T : never
61+
>(data)
62+
) {
63+
hash = data.value.receipt.transactionHash;
64+
}
65+
66+
updated = {
67+
...updated,
68+
writes: {
69+
...updated.writes,
70+
[data.writeId]: {
71+
...write,
72+
type: data.type,
73+
hash,
74+
userOpHash: data.type === "waitForUserOperationReceipt" ? data.userOpHash : write.userOpHash,
75+
events: [...write.events, data],
76+
},
6377
},
64-
},
65-
};
78+
};
79+
}
80+
81+
// Clear messages after processing
82+
messageBuffer.length = 0;
83+
return updated;
6684
});
67-
});
85+
}
86+
87+
const bufferInterval = 100;
88+
setInterval(flushMessageBuffer, bufferInterval);

0 commit comments

Comments
 (0)