diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 29c7208..0edd994 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -82,6 +82,8 @@ const Transaction: React.FC = () => {
= ({ txData, txDesc, + userDoc, + devDoc, internalOps, sendsEthToMiner, ethUSDPrice, @@ -80,6 +85,8 @@ const Details: React.FC = ({ }, [txData, fourBytesEntry]); const resolvedTxDesc = txDesc ?? fourBytesTxDesc; + const userMethod = txDesc ? userDoc?.methods[txDesc.signature] : undefined; + const devMethod = txDesc ? devDoc?.methods[txDesc.signature] : undefined; return ( @@ -353,6 +360,8 @@ const Details: React.FC = ({ paramTypes={resolvedTxDesc.functionFragment.inputs} txData={txData} hasParamNames={resolvedTxDesc === txDesc} + userMethod={userMethod} + devMethod={devMethod} /> )} diff --git a/src/transaction/decoder/DecodedParamRow.tsx b/src/transaction/decoder/DecodedParamRow.tsx index 988e536..bd94dc4 100644 --- a/src/transaction/decoder/DecodedParamRow.tsx +++ b/src/transaction/decoder/DecodedParamRow.tsx @@ -1,5 +1,9 @@ -import React, { ReactNode } from "react"; +import React, { ReactNode, useState } from "react"; import { ParamType } from "@ethersproject/abi"; +import { Switch } from "@headlessui/react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faQuestionCircle } from "@fortawesome/free-regular-svg-icons/faQuestionCircle"; +import { faQuestionCircle as faQuestionCircleSolid } from "@fortawesome/free-solid-svg-icons/faQuestionCircle"; import Uint256Decoder from "./Uint256Decoder"; import AddressDecoder from "./AddressDecoder"; import BooleanDecoder from "./BooleanDecoder"; @@ -13,6 +17,7 @@ type DecodedParamRowProps = { paramType: ParamType; txData: TransactionData; arrayElem?: number | undefined; + help?: string | undefined; }; const DecodedParamRow: React.FC = ({ @@ -22,71 +27,95 @@ const DecodedParamRow: React.FC = ({ paramType, txData, arrayElem, -}) => ( - <> - - - {prefix && {prefix}} - {arrayElem !== undefined ? ( - - {" "} - [{arrayElem}] - - ) : ( - <> - {paramType.name ?? param_{i}}{" "} - {i !== undefined && ( - ({i}) - )} - - )} - - {paramType.type} - - {paramType.baseType === "uint256" ? ( - - ) : paramType.baseType === "address" ? ( - - ) : paramType.baseType === "bool" ? ( - - ) : paramType.baseType === "bytes" ? ( - - ) : paramType.baseType === "tuple" || paramType.baseType === "array" ? ( - <> - ) : ( - r.toString() - )} - - - {paramType.baseType === "tuple" && - r.map((e: any, idx: number) => ( - { + const [showHelp, setShowHelp] = useState(false); + + return ( + <> + + +
+ {prefix && {prefix}} + {arrayElem !== undefined ? ( + + {" "} + [{arrayElem}] + ) : ( - param_{i}. - ) - } - i={idx} - r={e} - paramType={paramType.components[idx]} - txData={txData} - /> - ))} - {paramType.baseType === "array" && - r.map((e: any, idx: number) => ( - param_{i}} - r={e} - paramType={paramType.arrayChildren} - txData={txData} - arrayElem={idx} - /> - ))} - -); + <> + {paramType.name ?? param_{i}}{" "} + {i !== undefined && ( + ({i}) + )} + + )} + {help && ( + <> + {" "} + + + + + )} +
+ {help && showHelp &&
{help}
} + + {paramType.type} + + {paramType.baseType === "uint256" ? ( + + ) : paramType.baseType === "address" ? ( + + ) : paramType.baseType === "bool" ? ( + + ) : paramType.baseType === "bytes" ? ( + + ) : paramType.baseType === "tuple" || + paramType.baseType === "array" ? ( + <> + ) : ( + r.toString() + )} + + + {paramType.baseType === "tuple" && + r.map((e: any, idx: number) => ( + param_{i}. + ) + } + i={idx} + r={e} + paramType={paramType.components[idx]} + txData={txData} + /> + ))} + {paramType.baseType === "array" && + r.map((e: any, idx: number) => ( + param_{i}} + r={e} + paramType={paramType.arrayChildren} + txData={txData} + arrayElem={idx} + /> + ))} + + ); +}; export default React.memo(DecodedParamRow); diff --git a/src/transaction/decoder/DecodedParamsTable.tsx b/src/transaction/decoder/DecodedParamsTable.tsx index 636dd67..f7daee5 100644 --- a/src/transaction/decoder/DecodedParamsTable.tsx +++ b/src/transaction/decoder/DecodedParamsTable.tsx @@ -2,12 +2,15 @@ import React from "react"; import { ParamType, Result } from "@ethersproject/abi"; import DecodedParamRow from "./DecodedParamRow"; import { TransactionData } from "../../types"; +import { DevMethod, UserMethod } from "../../useSourcify"; type DecodedParamsTableProps = { args: Result; paramTypes: ParamType[]; txData: TransactionData; hasParamNames?: boolean; + userMethod?: UserMethod | undefined; + devMethod?: DevMethod | undefined; }; const DecodedParamsTable: React.FC = ({ @@ -15,6 +18,7 @@ const DecodedParamsTable: React.FC = ({ paramTypes, txData, hasParamNames = true, + devMethod, }) => ( @@ -43,6 +47,7 @@ const DecodedParamsTable: React.FC = ({ r={r} paramType={paramTypes[i]} txData={txData} + help={devMethod?.params?.[paramTypes[i].name]} /> ))} diff --git a/src/useSourcify.ts b/src/useSourcify.ts index b60fde9..0d6ea59 100644 --- a/src/useSourcify.ts +++ b/src/useSourcify.ts @@ -3,6 +3,33 @@ import { Interface } from "@ethersproject/abi"; import { TransactionData } from "./types"; import { sourcifyMetadata, SourcifySource, sourcifySourceFile } from "./url"; +export type UserMethod = { + notice?: string | undefined; +}; + +export type UserEvent = { + notice?: string | undefined; +}; + +export type UserDoc = { + kind: "user"; + version?: number | undefined; + notice?: string | undefined; + methods: Record; + events: Record; +}; + +export type DevMethod = { + params?: Record; + returns?: Record; +}; + +export type DevDoc = { + kind: "dev"; + version?: number | undefined; + methods: Record; +}; + export type Metadata = { version: string; language: string; @@ -33,8 +60,8 @@ export type Metadata = { }; output: { abi: any[]; - userdocs: any[]; - devdoc: any[]; + userdoc?: UserDoc | undefined; + devdoc?: DevDoc | undefined; }; };