Add devdoc params help to verified decoded input params
This commit is contained in:
parent
46ba7c477e
commit
ba3d721e14
|
@ -82,6 +82,8 @@ const Transaction: React.FC = () => {
|
|||
<Details
|
||||
txData={txData}
|
||||
txDesc={txDesc}
|
||||
userDoc={metadata?.output.userdoc}
|
||||
devDoc={metadata?.output.devdoc}
|
||||
internalOps={internalOps}
|
||||
sendsEthToMiner={sendsEthToMiner}
|
||||
ethUSDPrice={blockETHUSDPrice}
|
||||
|
|
|
@ -37,10 +37,13 @@ import PercentagePosition from "../components/PercentagePosition";
|
|||
import ModeTab from "../components/ModeTab";
|
||||
import DecodedParamsTable from "./decoder/DecodedParamsTable";
|
||||
import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes";
|
||||
import { DevDoc, UserDoc } from "../useSourcify";
|
||||
|
||||
type DetailsProps = {
|
||||
txData: TransactionData;
|
||||
txDesc: TransactionDescription | null | undefined;
|
||||
userDoc?: UserDoc | undefined;
|
||||
devDoc?: DevDoc | undefined;
|
||||
internalOps?: InternalOperation[];
|
||||
sendsEthToMiner: boolean;
|
||||
ethUSDPrice: BigNumber | undefined;
|
||||
|
@ -49,6 +52,8 @@ type DetailsProps = {
|
|||
const Details: React.FC<DetailsProps> = ({
|
||||
txData,
|
||||
txDesc,
|
||||
userDoc,
|
||||
devDoc,
|
||||
internalOps,
|
||||
sendsEthToMiner,
|
||||
ethUSDPrice,
|
||||
|
@ -80,6 +85,8 @@ const Details: React.FC<DetailsProps> = ({
|
|||
}, [txData, fourBytesEntry]);
|
||||
|
||||
const resolvedTxDesc = txDesc ?? fourBytesTxDesc;
|
||||
const userMethod = txDesc ? userDoc?.methods[txDesc.signature] : undefined;
|
||||
const devMethod = txDesc ? devDoc?.methods[txDesc.signature] : undefined;
|
||||
|
||||
return (
|
||||
<ContentFrame tabs>
|
||||
|
@ -353,6 +360,8 @@ const Details: React.FC<DetailsProps> = ({
|
|||
paramTypes={resolvedTxDesc.functionFragment.inputs}
|
||||
txData={txData}
|
||||
hasParamNames={resolvedTxDesc === txDesc}
|
||||
userMethod={userMethod}
|
||||
devMethod={devMethod}
|
||||
/>
|
||||
)}
|
||||
</Tab.Panel>
|
||||
|
|
|
@ -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<DecodedParamRowProps> = ({
|
||||
|
@ -22,71 +27,95 @@ const DecodedParamRow: React.FC<DecodedParamRowProps> = ({
|
|||
paramType,
|
||||
txData,
|
||||
arrayElem,
|
||||
}) => (
|
||||
<>
|
||||
<tr className="grid grid-cols-12 gap-x-2 py-2 hover:bg-gray-100">
|
||||
<td className="col-span-3 pl-1">
|
||||
{prefix && <span className="text-gray-300">{prefix}</span>}
|
||||
{arrayElem !== undefined ? (
|
||||
<span className="text-gray-400">
|
||||
{" "}
|
||||
[<span className="text-black">{arrayElem}</span>]
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
{paramType.name ?? <span className="italic">param_{i}</span>}{" "}
|
||||
{i !== undefined && (
|
||||
<span className="text-gray-400 text-xs">({i})</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className="col-span-1 text-gray-500">{paramType.type}</td>
|
||||
<td className="col-span-8 pr-1 font-code break-all">
|
||||
{paramType.baseType === "uint256" ? (
|
||||
<Uint256Decoder r={r} />
|
||||
) : paramType.baseType === "address" ? (
|
||||
<AddressDecoder r={r} txData={txData} />
|
||||
) : paramType.baseType === "bool" ? (
|
||||
<BooleanDecoder r={r} />
|
||||
) : paramType.baseType === "bytes" ? (
|
||||
<BytesDecoder r={r} />
|
||||
) : paramType.baseType === "tuple" || paramType.baseType === "array" ? (
|
||||
<></>
|
||||
) : (
|
||||
r.toString()
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
{paramType.baseType === "tuple" &&
|
||||
r.map((e: any, idx: number) => (
|
||||
<DecodedParamRow
|
||||
key={idx}
|
||||
prefix={
|
||||
paramType.name ? (
|
||||
paramType.name + "."
|
||||
help,
|
||||
}) => {
|
||||
const [showHelp, setShowHelp] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<tr className="grid grid-cols-12 gap-x-2 py-2 hover:bg-gray-100">
|
||||
<td className="col-span-3 pl-1">
|
||||
<div>
|
||||
{prefix && <span className="text-gray-300">{prefix}</span>}
|
||||
{arrayElem !== undefined ? (
|
||||
<span className="text-gray-400">
|
||||
{" "}
|
||||
[<span className="text-black">{arrayElem}</span>]
|
||||
</span>
|
||||
) : (
|
||||
<span className="italic">param_{i}.</span>
|
||||
)
|
||||
}
|
||||
i={idx}
|
||||
r={e}
|
||||
paramType={paramType.components[idx]}
|
||||
txData={txData}
|
||||
/>
|
||||
))}
|
||||
{paramType.baseType === "array" &&
|
||||
r.map((e: any, idx: number) => (
|
||||
<DecodedParamRow
|
||||
key={idx}
|
||||
prefix={paramType.name ?? <span className="italic">param_{i}</span>}
|
||||
r={e}
|
||||
paramType={paramType.arrayChildren}
|
||||
txData={txData}
|
||||
arrayElem={idx}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
<>
|
||||
{paramType.name ?? <span className="italic">param_{i}</span>}{" "}
|
||||
{i !== undefined && (
|
||||
<span className="text-gray-400 text-xs">({i})</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{help && (
|
||||
<>
|
||||
{" "}
|
||||
<Switch
|
||||
checked={showHelp}
|
||||
onChange={setShowHelp}
|
||||
className="text-gray-500"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={showHelp ? faQuestionCircleSolid : faQuestionCircle}
|
||||
size="1x"
|
||||
/>
|
||||
</Switch>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{help && showHelp && <div className="mt-2 text-gray-400">{help}</div>}
|
||||
</td>
|
||||
<td className="col-span-1 text-gray-500">{paramType.type}</td>
|
||||
<td className="col-span-8 pr-1 font-code break-all">
|
||||
{paramType.baseType === "uint256" ? (
|
||||
<Uint256Decoder r={r} />
|
||||
) : paramType.baseType === "address" ? (
|
||||
<AddressDecoder r={r} txData={txData} />
|
||||
) : paramType.baseType === "bool" ? (
|
||||
<BooleanDecoder r={r} />
|
||||
) : paramType.baseType === "bytes" ? (
|
||||
<BytesDecoder r={r} />
|
||||
) : paramType.baseType === "tuple" ||
|
||||
paramType.baseType === "array" ? (
|
||||
<></>
|
||||
) : (
|
||||
r.toString()
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
{paramType.baseType === "tuple" &&
|
||||
r.map((e: any, idx: number) => (
|
||||
<DecodedParamRow
|
||||
key={idx}
|
||||
prefix={
|
||||
paramType.name ? (
|
||||
paramType.name + "."
|
||||
) : (
|
||||
<span className="italic">param_{i}.</span>
|
||||
)
|
||||
}
|
||||
i={idx}
|
||||
r={e}
|
||||
paramType={paramType.components[idx]}
|
||||
txData={txData}
|
||||
/>
|
||||
))}
|
||||
{paramType.baseType === "array" &&
|
||||
r.map((e: any, idx: number) => (
|
||||
<DecodedParamRow
|
||||
key={idx}
|
||||
prefix={paramType.name ?? <span className="italic">param_{i}</span>}
|
||||
r={e}
|
||||
paramType={paramType.arrayChildren}
|
||||
txData={txData}
|
||||
arrayElem={idx}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(DecodedParamRow);
|
||||
|
|
|
@ -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<DecodedParamsTableProps> = ({
|
||||
|
@ -15,6 +18,7 @@ const DecodedParamsTable: React.FC<DecodedParamsTableProps> = ({
|
|||
paramTypes,
|
||||
txData,
|
||||
hasParamNames = true,
|
||||
devMethod,
|
||||
}) => (
|
||||
<table className="border w-full">
|
||||
<thead>
|
||||
|
@ -43,6 +47,7 @@ const DecodedParamsTable: React.FC<DecodedParamsTableProps> = ({
|
|||
r={r}
|
||||
paramType={paramTypes[i]}
|
||||
txData={txData}
|
||||
help={devMethod?.params?.[paramTypes[i].name]}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
|
|
|
@ -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<string, UserMethod>;
|
||||
events: Record<string, UserEvent>;
|
||||
};
|
||||
|
||||
export type DevMethod = {
|
||||
params?: Record<string, string>;
|
||||
returns?: Record<string, string>;
|
||||
};
|
||||
|
||||
export type DevDoc = {
|
||||
kind: "dev";
|
||||
version?: number | undefined;
|
||||
methods: Record<string, DevMethod>;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue