From 85c58f4164d5fd6ef031bd167402faf5a10a5587 Mon Sep 17 00:00:00 2001 From: karooolis Date: Wed, 9 Oct 2024 16:58:00 +0300 Subject: [PATCH 01/16] inital txs view --- .../observe/TransactionTableRow.tsx | 110 ++++++++++++++++++ .../observe/TransactionsTable.tsx | 12 ++ .../worlds/[worldAddress]/observe/Write.tsx | 31 ----- .../worlds/[worldAddress]/observe/Writes.tsx | 26 ----- 4 files changed, 122 insertions(+), 57 deletions(-) delete mode 100644 packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Write.tsx delete mode 100644 packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Writes.tsx diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx index 1784f8f69d..a88913a0af 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx @@ -4,6 +4,7 @@ import { Row, flexRender } from "@tanstack/react-table"; import { Separator } from "../../../../../../components/ui/Separator"; import { Skeleton } from "../../../../../../components/ui/Skeleton"; import { TableCell, TableRow } from "../../../../../../components/ui/Table"; +import { type Write } from "../../../../../../observer/store"; import { cn } from "../../../../../../utils"; import { Confirmations } from "./Confirmations"; import { columns } from "./TransactionsTable"; @@ -151,6 +152,8 @@ export function TransactionTableRow({ row }: { row: Row }) { ) : null} + + {data.write && } )} @@ -159,3 +162,110 @@ export function TransactionTableRow({ row }: { row: Row }) { ); } + +function Timing({ time: start, events }: Write) { + const maxLen = Math.max(...events.map((event) => event.time - start)); + + const eventPriority = { + write: 1, + "write:result": 2, + waitForTransaction: 3, + "waitForTransaction:result": 4, + waitForTransactionReceipt: 5, + "waitForTransactionReceipt:result": 6, + }; + + const eventMap = events.reduce( + (acc, event) => { + acc[event.type] = event.time; + return acc; + }, + {} as Record, + ); + + const groupedEvents = events.reduce( + (acc, event) => { + const baseType = event.type.split(":")[0]; + if (!acc[baseType]) { + acc[baseType] = []; + } + acc[baseType].push(event); + return acc; + }, + {} as Record, + ); + + const sortedEvents = Object.values(groupedEvents) + .flat() + .sort((a, b) => { + const priorityA = eventPriority[a.type as keyof typeof eventPriority] || Infinity; + const priorityB = eventPriority[b.type as keyof typeof eventPriority] || Infinity; + return priorityA - priorityB; + }); + + console.log(events); + + return ( + <> + + +
+

Timing

+ +
+
+ {sortedEvents.map((event, index) => { + const type = event.type; + const baseType = type.split(":")[0]; + const isResult = type.endsWith(":result"); + + let duration: number; + let startOffset: number; + + if (isResult) { + const startTime = eventMap[baseType] || start; + duration = event.time - startTime; + startOffset = startTime - start; + } else { + duration = (eventMap[`${type}:result`] || event.time) - event.time; + startOffset = event.time - start; + } + + const startPercentage = (startOffset / maxLen) * 100; + const widthPercentage = (duration / maxLen) * 100; + + if (isResult) { + return null; + } + + return ( +
+ + {type}: + +
+
+
+ {duration}ms +
+ ); + })} +
+
+
+ + ); +} diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx index 96e5ae58fb..daf2c91983 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx @@ -85,6 +85,18 @@ export const columns = [ return ; }, }), + columnHelper.accessor("write", { + header: "Timing", + cell: () => { + return ( +
+ + + +
+ ); + }, + }), ]; export function TransactionsTable() { diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Write.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Write.tsx deleted file mode 100644 index daa8bdf225..0000000000 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Write.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client"; - -import { type Write } from "../../../../../../observer/store"; -import { msPerViewportWidth } from "./common"; - -export type Props = Write; - -export function Write({ functionSignature, time: start, events }: Props) { - return ( -
-
- {functionSignature} {new Date(start).toLocaleTimeString()} -
-
- {events.map((event) => ( -
-
-
-
- {event.type} {event.time - start}ms -
-
-
- ))} -
-
- ); -} diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Writes.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Writes.tsx deleted file mode 100644 index 821e849b34..0000000000 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/Writes.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import { useStore } from "zustand"; -import { KeepInView } from "../../../../../../components/KeepInView"; -import { store } from "../../../../../../observer/store"; -import { Write } from "./Write"; - -export function Writes() { - const writes = useStore(store, (state) => Object.values(state.writes)); - - return ( - // TODO: replace with h-full once container is stretched to full height -
- -
- {writes.length === 0 ? <>Waiting for transactions… : null} - {writes.map((write) => ( -
- -
- ))} -
-
-
- ); -} From f78595c645905678c44760515698222079196ff9 Mon Sep 17 00:00:00 2001 From: karooolis Date: Thu, 10 Oct 2024 11:07:18 +0300 Subject: [PATCH 02/16] add timings header + row --- .../observe/TimingRowExpanded.tsx | 37 ++++++ .../observe/TimingRowHeader.tsx | 26 ++++ .../observe/TransactionTableRow.tsx | 118 +----------------- .../observe/TransactionsTable.tsx | 13 +- .../[worldAddress]/observe/useTimings.ts | 47 +++++++ .../observe/useTransactionWatcher.ts | 2 +- 6 files changed, 120 insertions(+), 123 deletions(-) create mode 100644 packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx create mode 100644 packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx create mode 100644 packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx new file mode 100644 index 0000000000..7ffbe378e8 --- /dev/null +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx @@ -0,0 +1,37 @@ +import { Separator } from "../../../../../../components/ui/Separator"; +import { type Write } from "../../../../../../observer/store"; +import { cn } from "../../../../../../utils"; +import { useTimings } from "./useTimings"; + +export function TimingRowExpanded(write: Write) { + const timings = useTimings(write); + return ( + <> + +
+

Timing

+
+
+ {timings.map((timing) => ( + <> + {timing.label}: +
+ {timing.duration}ms + + ))} +
+
+
+ + ); +} diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx new file mode 100644 index 0000000000..80374120a2 --- /dev/null +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx @@ -0,0 +1,26 @@ +import { type Write } from "../../../../../../observer/store"; +import { cn } from "../../../../../../utils"; +import { useTimings } from "./useTimings"; + +export function TimingRowHeader(write: Write) { + const timings = useTimings(write); + return ( +
+ {timings.map((timing) => ( +
+ ))} +
+ ); +} diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx index a88913a0af..ed75eee786 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx @@ -4,9 +4,9 @@ import { Row, flexRender } from "@tanstack/react-table"; import { Separator } from "../../../../../../components/ui/Separator"; import { Skeleton } from "../../../../../../components/ui/Skeleton"; import { TableCell, TableRow } from "../../../../../../components/ui/Table"; -import { type Write } from "../../../../../../observer/store"; import { cn } from "../../../../../../utils"; import { Confirmations } from "./Confirmations"; +import { TimingRowExpanded } from "./TimingRowExpanded"; import { columns } from "./TransactionsTable"; import { WatchedTransaction } from "./useTransactionWatcher"; @@ -79,7 +79,6 @@ export function TransactionTableRow({ row }: { row: Row }) {
-

Inputs

{Array.isArray(data.functionData?.args) && data.functionData?.args.length > 0 ? ( @@ -101,7 +100,6 @@ export function TransactionTableRow({ row }: { row: Row }) { {data.error ? ( <> -

Error

{data.error ? ( @@ -118,9 +116,8 @@ export function TransactionTableRow({ row }: { row: Row }) { {!data.error ? ( <> - -
-

Logs

+
+

Logs

{Array.isArray(logs) && logs.length > 0 ? (
    @@ -153,7 +150,7 @@ export function TransactionTableRow({ row }: { row: Row }) { ) : null} - {data.write && } + {data.write && } )} @@ -162,110 +159,3 @@ export function TransactionTableRow({ row }: { row: Row }) { ); } - -function Timing({ time: start, events }: Write) { - const maxLen = Math.max(...events.map((event) => event.time - start)); - - const eventPriority = { - write: 1, - "write:result": 2, - waitForTransaction: 3, - "waitForTransaction:result": 4, - waitForTransactionReceipt: 5, - "waitForTransactionReceipt:result": 6, - }; - - const eventMap = events.reduce( - (acc, event) => { - acc[event.type] = event.time; - return acc; - }, - {} as Record, - ); - - const groupedEvents = events.reduce( - (acc, event) => { - const baseType = event.type.split(":")[0]; - if (!acc[baseType]) { - acc[baseType] = []; - } - acc[baseType].push(event); - return acc; - }, - {} as Record, - ); - - const sortedEvents = Object.values(groupedEvents) - .flat() - .sort((a, b) => { - const priorityA = eventPriority[a.type as keyof typeof eventPriority] || Infinity; - const priorityB = eventPriority[b.type as keyof typeof eventPriority] || Infinity; - return priorityA - priorityB; - }); - - console.log(events); - - return ( - <> - - -
    -

    Timing

    - -
    -
    - {sortedEvents.map((event, index) => { - const type = event.type; - const baseType = type.split(":")[0]; - const isResult = type.endsWith(":result"); - - let duration: number; - let startOffset: number; - - if (isResult) { - const startTime = eventMap[baseType] || start; - duration = event.time - startTime; - startOffset = startTime - start; - } else { - duration = (eventMap[`${type}:result`] || event.time) - event.time; - startOffset = event.time - start; - } - - const startPercentage = (startOffset / maxLen) * 100; - const widthPercentage = (duration / maxLen) * 100; - - if (isResult) { - return null; - } - - return ( -
    - - {type}: - -
    -
    -
    - {duration}ms -
    - ); - })} -
    -
    -
    - - ); -} diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx index daf2c91983..f78f6ed25d 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx @@ -10,6 +10,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from ". import { TruncatedHex } from "../../../../../../components/ui/TruncatedHex"; import { BlockExplorerLink } from "./BlockExplorerLink"; import { TimeAgo } from "./TimeAgo"; +import { TimingRowHeader } from "./TimingRowHeader"; import { TransactionTableRow } from "./TransactionTableRow"; import { WatchedTransaction, useTransactionWatcher } from "./useTransactionWatcher"; @@ -87,14 +88,10 @@ export const columns = [ }), columnHelper.accessor("write", { header: "Timing", - cell: () => { - return ( -
    - - - -
    - ); + cell: (row) => { + const write = row.getValue(); + if (!write) return ; + return ; }, }), ]; diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts new file mode 100644 index 0000000000..c92c9b9a6b --- /dev/null +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts @@ -0,0 +1,47 @@ +import { isDefined } from "@latticexyz/common/utils"; +import { type Write } from "../../../../../../observer/store"; + +const eventConfig = { + write: { priority: 1, label: "write" }, + "write:result": { priority: 2 }, + waitForTransaction: { priority: 3, label: "state update" }, + "waitForTransaction:result": { priority: 4 }, + waitForTransactionReceipt: { priority: 5, label: "transaction receipt" }, + "waitForTransactionReceipt:result": { priority: 6 }, +} as const; + +type EventType = keyof typeof eventConfig; + +export function useTimings({ time: start, events }: Write) { + const maxLen = Math.max(...events.map((event) => event.time - start)); + const sortedEvents = Object.values(events).sort((a, b) => { + const priorityA = eventConfig[a.type as EventType]?.priority ?? Infinity; + const priorityB = eventConfig[b.type as EventType]?.priority ?? Infinity; + return priorityA - priorityB; + }); + + const processedEvents = sortedEvents + .map((event) => { + const type = event.type as EventType; + if (type.endsWith(":result")) return; + + const writeResult = events.find((e) => e.type === `${type}:result`); + const duration = (writeResult?.time || event.time) - event.time; + const startOffset = event.time - start; + + const startPercentage = (startOffset / maxLen) * 100; + const widthPercentage = (duration / maxLen) * 100; + + const config = eventConfig[type]; + return { + type, + label: "label" in config ? config.label : type, + duration, + startPercentage, + widthPercentage, + }; + }) + .filter(isDefined); + + return processedEvents; +} diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts index 3c89fcc87e..4e953fb576 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts @@ -17,7 +17,7 @@ import { getTransaction, simulateContract, waitForTransactionReceipt } from "wag import { useStore } from "zustand"; import { useCallback, useEffect, useMemo, useState } from "react"; import { Message } from "../../../../../../observer/messages"; -import { Write, store } from "../../../../../../observer/store"; +import { type Write, store } from "../../../../../../observer/store"; import { useChain } from "../../../../hooks/useChain"; import { useWorldAbiQuery } from "../../../../queries/useWorldAbiQuery"; From 33cb891f5d13dbd52d2045de6bc1e063401b3fe7 Mon Sep 17 00:00:00 2001 From: karooolis Date: Thu, 10 Oct 2024 14:03:17 +0300 Subject: [PATCH 03/16] update timings colors --- .../worlds/[worldAddress]/observe/TimingRowExpanded.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx index 7ffbe378e8..106b4555ba 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx @@ -17,9 +17,9 @@ export function TimingRowExpanded(write: Write) { {timing.label}:
    Date: Fri, 11 Oct 2024 09:07:58 +0300 Subject: [PATCH 04/16] add pending status to logs --- .../[worldAddress]/observe/TransactionTableRow.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx index ed75eee786..9b7d4af1ef 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionTableRow.tsx @@ -102,13 +102,9 @@ export function TransactionTableRow({ row }: { row: Row }) {

    Error

    - {data.error ? ( -
    - {data.error.message} -
    - ) : ( -

    No error

    - )} +
    + {data.error.message} +
    ) : null} @@ -118,7 +114,7 @@ export function TransactionTableRow({ row }: { row: Row }) {

    Logs

    - {Array.isArray(logs) && logs.length > 0 ? ( + {Array.isArray(logs) && logs.length > 10 ? (
      {logs.map((log, idx) => { @@ -143,6 +139,8 @@ export function TransactionTableRow({ row }: { row: Row }) { })}
    + ) : status === "pending" ? ( + ) : (

    No logs

    )} From 879a6c364244ebb2a5183e3653188f88a5cf4a33 Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 10:00:48 +0300 Subject: [PATCH 05/16] update colors + timings width --- .../worlds/[worldAddress]/observe/TimingRowHeader.tsx | 8 ++++---- .../worlds/[worldAddress]/observe/TransactionsTable.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx index 80374120a2..825899ae55 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx @@ -5,15 +5,15 @@ import { useTimings } from "./useTimings"; export function TimingRowHeader(write: Write) { const timings = useTimings(write); return ( -
    +
    {timings.map((timing) => (
    { const write = row.getValue(); - if (!write) return ; + if (!write) return ; return ; }, }), From 3e2186c71e89ce7e202df4aa05ef3733546e9938 Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 10:33:51 +0300 Subject: [PATCH 06/16] update unavailable timings with n/a --- .../worlds/[worldAddress]/observe/TransactionsTable.tsx | 2 +- packages/explorer/src/app/(explorer)/utils/timeAgo.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx index 36b64933ac..c0055ab7ef 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsTable.tsx @@ -90,7 +90,7 @@ export const columns = [ header: "Timing", cell: (row) => { const write = row.getValue(); - if (!write) return ; + if (!write) return N/A; return ; }, }), diff --git a/packages/explorer/src/app/(explorer)/utils/timeAgo.ts b/packages/explorer/src/app/(explorer)/utils/timeAgo.ts index 1ed9496828..dc9f2bcac4 100644 --- a/packages/explorer/src/app/(explorer)/utils/timeAgo.ts +++ b/packages/explorer/src/app/(explorer)/utils/timeAgo.ts @@ -22,5 +22,5 @@ export function timeAgo(timestamp: bigint) { } } - return "just now"; + return "0s ago"; } From d7569300911359782a84c952ee9b861dcfa8e082 Mon Sep 17 00:00:00 2001 From: Karolis Ramanauskas Date: Fri, 11 Oct 2024 10:34:41 +0300 Subject: [PATCH 07/16] Create eighty-humans-divide.md --- .changeset/eighty-humans-divide.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/eighty-humans-divide.md diff --git a/.changeset/eighty-humans-divide.md b/.changeset/eighty-humans-divide.md new file mode 100644 index 0000000000..d4c4efc7db --- /dev/null +++ b/.changeset/eighty-humans-divide.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/explorer": patch +--- + +Tranasctions in Observe tab are now populated with timing metrics when using the observer transport wrapper. From d17c8900297bb53a538f1ba9917de17c9fc45a5a Mon Sep 17 00:00:00 2001 From: Karolis Ramanauskas Date: Fri, 11 Oct 2024 10:37:54 +0300 Subject: [PATCH 08/16] Update eighty-humans-divide.md --- .changeset/eighty-humans-divide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eighty-humans-divide.md b/.changeset/eighty-humans-divide.md index d4c4efc7db..71f8c59f1b 100644 --- a/.changeset/eighty-humans-divide.md +++ b/.changeset/eighty-humans-divide.md @@ -2,4 +2,4 @@ "@latticexyz/explorer": patch --- -Tranasctions in Observe tab are now populated with timing metrics when using the observer transport wrapper. +Transactions in Observe tab are now populated with timing metrics when using the observer transport wrapper. From da26c7ab7ffb9c23dec7266581f8b712073a4866 Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 10:41:54 +0300 Subject: [PATCH 09/16] update markup --- .../worlds/[worldAddress]/observe/TimingRowExpanded.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx index 106b4555ba..67295392eb 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowExpanded.tsx @@ -15,7 +15,7 @@ export function TimingRowExpanded(write: Write) { {timings.map((timing) => ( <> {timing.label}: -
    Date: Fri, 11 Oct 2024 10:42:43 +0300 Subject: [PATCH 10/16] update useTimings --- .../[chainName]/worlds/[worldAddress]/observe/useTimings.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts index c92c9b9a6b..e6cd38a0ed 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts @@ -20,7 +20,7 @@ export function useTimings({ time: start, events }: Write) { return priorityA - priorityB; }); - const processedEvents = sortedEvents + return sortedEvents .map((event) => { const type = event.type as EventType; if (type.endsWith(":result")) return; @@ -42,6 +42,4 @@ export function useTimings({ time: start, events }: Write) { }; }) .filter(isDefined); - - return processedEvents; } From 18b360264525a0f61fdaef9888348bddd1ff64ea Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 10:43:14 +0300 Subject: [PATCH 11/16] remove priorty infinity --- .../[chainName]/worlds/[worldAddress]/observe/useTimings.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts index e6cd38a0ed..8a78f7df9b 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts @@ -15,8 +15,8 @@ type EventType = keyof typeof eventConfig; export function useTimings({ time: start, events }: Write) { const maxLen = Math.max(...events.map((event) => event.time - start)); const sortedEvents = Object.values(events).sort((a, b) => { - const priorityA = eventConfig[a.type as EventType]?.priority ?? Infinity; - const priorityB = eventConfig[b.type as EventType]?.priority ?? Infinity; + const priorityA = eventConfig[a.type as EventType]?.priority; + const priorityB = eventConfig[b.type as EventType]?.priority; return priorityA - priorityB; }); From 80ed7069f606199fd83ca1701ef5020d1505dcaa Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 10:44:47 +0300 Subject: [PATCH 12/16] add endTime --- .../[chainName]/worlds/[worldAddress]/observe/useTimings.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts index 8a78f7df9b..5acd6882fd 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTimings.ts @@ -26,7 +26,8 @@ export function useTimings({ time: start, events }: Write) { if (type.endsWith(":result")) return; const writeResult = events.find((e) => e.type === `${type}:result`); - const duration = (writeResult?.time || event.time) - event.time; + const endTime = writeResult?.time ?? event.time; + const duration = endTime - event.time; const startOffset = event.time - start; const startPercentage = (startOffset / maxLen) * 100; From 994aa6a4b660809651809f0876fe7139d35a700a Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 13:32:21 +0300 Subject: [PATCH 13/16] add metrics to time column --- .../worlds/[worldAddress]/observe/TimeAgo.tsx | 2 +- .../[worldAddress]/observe/TimingRowHeader.tsx | 2 +- .../observe/TransactionsTable.tsx | 17 +++++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimeAgo.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimeAgo.tsx index ac6babbfc5..8c6f7c0003 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimeAgo.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimeAgo.tsx @@ -13,7 +13,7 @@ export function TimeAgo({ timestamp }: { timestamp: bigint }) { }, [timestamp]); return ( - + {ago} ); diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx index 825899ae55..eda32a5d0c 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TimingRowHeader.tsx @@ -5,7 +5,7 @@ import { useTimings } from "./useTimings"; export function TimingRowHeader(write: Write) { const timings = useTimings(write); return ( -
    +
    {timings.map((timing) => (
    { const timestamp = row.getValue(); - if (!timestamp) return ; - return ; - }, - }), - columnHelper.accessor("write", { - header: "Timing", - cell: (row) => { - const write = row.getValue(); - if (!write) return N/A; - return ; + const write = row.row.original.write; + return ( + <> + {timestamp ? : } + {write && } + + ); }, }), ]; From cbe5e15418e6a3bd406e21b73a2ebc39044a0382 Mon Sep 17 00:00:00 2001 From: Karolis Ramanauskas Date: Fri, 11 Oct 2024 13:32:33 +0300 Subject: [PATCH 14/16] Update .changeset/eighty-humans-divide.md Co-authored-by: Kevin Ingersoll --- .changeset/eighty-humans-divide.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.changeset/eighty-humans-divide.md b/.changeset/eighty-humans-divide.md index 71f8c59f1b..09c87d8e01 100644 --- a/.changeset/eighty-humans-divide.md +++ b/.changeset/eighty-humans-divide.md @@ -2,4 +2,12 @@ "@latticexyz/explorer": patch --- -Transactions in Observe tab are now populated with timing metrics when using the observer transport wrapper. +Transactions in Observe tab are now populated with timing metrics when using the `observer` Viem decorator in local projects. + +You can wire up your local project to use transaction timings with: +``` +import { observer } from "@latticexyz/explorer/observer"; + +// Extend the Viem client that is performing writes +walletClient.extend(observer()); +``` From 02e2c3846a67891a2592f07f2203e6dc4595685b Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 13:38:35 +0300 Subject: [PATCH 15/16] prettier changeset --- .changeset/eighty-humans-divide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/eighty-humans-divide.md b/.changeset/eighty-humans-divide.md index 09c87d8e01..40dd5e3976 100644 --- a/.changeset/eighty-humans-divide.md +++ b/.changeset/eighty-humans-divide.md @@ -5,6 +5,7 @@ Transactions in Observe tab are now populated with timing metrics when using the `observer` Viem decorator in local projects. You can wire up your local project to use transaction timings with: + ``` import { observer } from "@latticexyz/explorer/observer"; From 016f353d241414711c216da0156ec8ffd2902773 Mon Sep 17 00:00:00 2001 From: karooolis Date: Fri, 11 Oct 2024 13:53:14 +0300 Subject: [PATCH 16/16] filter observe calls by world address --- .../[worldAddress]/observe/useTransactionWatcher.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts index 4e953fb576..58d56c2a9e 100644 --- a/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts +++ b/packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useTransactionWatcher.ts @@ -135,14 +135,14 @@ export function useTransactionWatcher() { useEffect(() => { for (const write of Object.values(observerWrites)) { const hash = write.hash; - if (write.type === "waitForTransactionReceipt" && hash) { + if (write.type === "waitForTransactionReceipt" && hash && write.address === worldAddress) { const transaction = transactions.find((transaction) => transaction.hash === hash); if (!transaction) { handleTransaction(hash, BigInt(write.time) / 1000n); } } } - }, [handleTransaction, observerWrites, transactions]); + }, [handleTransaction, observerWrites, transactions, worldAddress]); useWatchBlocks({ onBlock(block) { @@ -159,6 +159,8 @@ export function useTransactionWatcher() { const mergedMap = new Map(); for (const write of Object.values(observerWrites)) { + if (write.address !== worldAddress) continue; + const parsedAbiItem = parseAbiItem(`function ${write.functionSignature}`) as AbiFunction; const writeResult = write.events.find((event): event is Message<"write:result"> => event.type === "write:result"); @@ -188,7 +190,7 @@ export function useTransactionWatcher() { } return Array.from(mergedMap.values()).sort((a, b) => Number(b.timestamp ?? 0n) - Number(a.timestamp ?? 0n)); - }, [transactions, observerWrites]); + }, [observerWrites, worldAddress, transactions]); return mergedTransactions; }