From 96f6b8aa04f0d0f3d407af00ce46cd894aaf759d Mon Sep 17 00:00:00 2001 From: ByteAtATime Date: Tue, 11 Jun 2024 07:54:17 -0700 Subject: [PATCH 01/11] Better transaction result formatting in debug page (#853) Co-authored-by: Shiv Bhonde --- .../contract/ReadOnlyFunctionForm.tsx | 10 +- .../debug/_components/contract/TxReceipt.tsx | 17 +-- .../_components/contract/utilsDisplay.tsx | 108 ++++++++++++++---- .../scaffold-eth/Input/IntegerInput.tsx | 2 +- 4 files changed, 99 insertions(+), 38 deletions(-) diff --git a/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx b/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx index 9ccc37fed..a0d097a53 100644 --- a/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +++ b/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx @@ -76,17 +76,17 @@ export const ReadOnlyFunctionForm = ({

{inputElements} -
-
+
+
{result !== null && result !== undefined && ( -
+

Result:

-
{displayTxResult(result)}
+
{displayTxResult(result, "sm")}
)}
diff --git a/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx b/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx index f5d212993..3148affdf 100644 --- a/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +++ b/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx @@ -1,5 +1,6 @@ -import { ReactElement } from "react"; -import { TransactionBase, TransactionReceipt, formatEther, isAddress } from "viem"; +import { ReactElement, useState } from "react"; +import { TransactionBase, TransactionReceipt, formatEther, isAddress, isHex } from "viem"; +import { ArrowsRightLeftIcon } from "@heroicons/react/24/solid"; import { Address } from "~~/components/scaffold-eth"; import { replacer } from "~~/utils/scaffold-eth/common"; @@ -13,44 +14,101 @@ type DisplayContent = | undefined | unknown; +type ResultFontSize = "sm" | "base" | "xs" | "lg" | "xl" | "2xl" | "3xl"; + export const displayTxResult = ( displayContent: DisplayContent | DisplayContent[], - asText = false, + fontSize: ResultFontSize = "base", ): string | ReactElement | number => { if (displayContent == null) { return ""; } if (typeof displayContent === "bigint") { - try { - const asNumber = Number(displayContent); - if (asNumber <= Number.MAX_SAFE_INTEGER && asNumber >= Number.MIN_SAFE_INTEGER) { - return asNumber; - } else { - return "Ξ" + formatEther(displayContent); - } - } catch (e) { - return "Ξ" + formatEther(displayContent); - } + return ; } - if (typeof displayContent === "string" && isAddress(displayContent)) { - return asText ? displayContent :
; + if (typeof displayContent === "string") { + if (isAddress(displayContent)) { + return
; + } + + if (isHex(displayContent)) { + return displayContent; // don't add quotes + } } if (Array.isArray(displayContent)) { - const mostReadable = (v: DisplayContent) => - ["number", "boolean"].includes(typeof v) ? v : displayTxResultAsText(v); - const displayable = JSON.stringify(displayContent.map(mostReadable), replacer); - - return asText ? ( - displayable - ) : ( - {displayable.replaceAll(",", ",\n")} - ); + return ; + } + + if (typeof displayContent === "object") { + return ; } return JSON.stringify(displayContent, replacer, 2); }; -const displayTxResultAsText = (displayContent: DisplayContent) => displayTxResult(displayContent, true); +const NumberDisplay = ({ value }: { value: bigint }) => { + const [isEther, setIsEther] = useState(false); + + const asNumber = Number(value); + if (asNumber <= Number.MAX_SAFE_INTEGER && asNumber >= Number.MIN_SAFE_INTEGER) { + return String(value); + } + + return ( +
+ {isEther ? "Ξ" + formatEther(value) : String(value)} + + + +
+ ); +}; + +export const ObjectFieldDisplay = ({ + name, + value, + size, + leftPad = true, +}: { + name: string; + value: DisplayContent; + size: ResultFontSize; + leftPad?: boolean; +}) => { + return ( +
+ {name}: + {displayTxResult(value, size)} +
+ ); +}; + +const ArrayDisplay = ({ values, size }: { values: DisplayContent[]; size: ResultFontSize }) => { + return ( +
+ {values.length ? "array" : "[]"} + {values.map((v, i) => ( + + ))} +
+ ); +}; + +const StructDisplay = ({ struct, size }: { struct: Record; size: ResultFontSize }) => { + return ( +
+ struct + {Object.entries(struct).map(([k, v]) => ( + + ))} +
+ ); +}; diff --git a/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx b/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx index f9b436124..4fde183e0 100644 --- a/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +++ b/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx @@ -47,7 +47,7 @@ export const IntegerInput = ({ !disableMultiplyBy1e18 && (