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
|
<Details
|
||||||
txData={txData}
|
txData={txData}
|
||||||
txDesc={txDesc}
|
txDesc={txDesc}
|
||||||
|
userDoc={metadata?.output.userdoc}
|
||||||
|
devDoc={metadata?.output.devdoc}
|
||||||
internalOps={internalOps}
|
internalOps={internalOps}
|
||||||
sendsEthToMiner={sendsEthToMiner}
|
sendsEthToMiner={sendsEthToMiner}
|
||||||
ethUSDPrice={blockETHUSDPrice}
|
ethUSDPrice={blockETHUSDPrice}
|
||||||
|
|
|
@ -37,10 +37,13 @@ import PercentagePosition from "../components/PercentagePosition";
|
||||||
import ModeTab from "../components/ModeTab";
|
import ModeTab from "../components/ModeTab";
|
||||||
import DecodedParamsTable from "./decoder/DecodedParamsTable";
|
import DecodedParamsTable from "./decoder/DecodedParamsTable";
|
||||||
import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes";
|
import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes";
|
||||||
|
import { DevDoc, UserDoc } from "../useSourcify";
|
||||||
|
|
||||||
type DetailsProps = {
|
type DetailsProps = {
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
txDesc: TransactionDescription | null | undefined;
|
txDesc: TransactionDescription | null | undefined;
|
||||||
|
userDoc?: UserDoc | undefined;
|
||||||
|
devDoc?: DevDoc | undefined;
|
||||||
internalOps?: InternalOperation[];
|
internalOps?: InternalOperation[];
|
||||||
sendsEthToMiner: boolean;
|
sendsEthToMiner: boolean;
|
||||||
ethUSDPrice: BigNumber | undefined;
|
ethUSDPrice: BigNumber | undefined;
|
||||||
|
@ -49,6 +52,8 @@ type DetailsProps = {
|
||||||
const Details: React.FC<DetailsProps> = ({
|
const Details: React.FC<DetailsProps> = ({
|
||||||
txData,
|
txData,
|
||||||
txDesc,
|
txDesc,
|
||||||
|
userDoc,
|
||||||
|
devDoc,
|
||||||
internalOps,
|
internalOps,
|
||||||
sendsEthToMiner,
|
sendsEthToMiner,
|
||||||
ethUSDPrice,
|
ethUSDPrice,
|
||||||
|
@ -80,6 +85,8 @@ const Details: React.FC<DetailsProps> = ({
|
||||||
}, [txData, fourBytesEntry]);
|
}, [txData, fourBytesEntry]);
|
||||||
|
|
||||||
const resolvedTxDesc = txDesc ?? fourBytesTxDesc;
|
const resolvedTxDesc = txDesc ?? fourBytesTxDesc;
|
||||||
|
const userMethod = txDesc ? userDoc?.methods[txDesc.signature] : undefined;
|
||||||
|
const devMethod = txDesc ? devDoc?.methods[txDesc.signature] : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContentFrame tabs>
|
<ContentFrame tabs>
|
||||||
|
@ -353,6 +360,8 @@ const Details: React.FC<DetailsProps> = ({
|
||||||
paramTypes={resolvedTxDesc.functionFragment.inputs}
|
paramTypes={resolvedTxDesc.functionFragment.inputs}
|
||||||
txData={txData}
|
txData={txData}
|
||||||
hasParamNames={resolvedTxDesc === txDesc}
|
hasParamNames={resolvedTxDesc === txDesc}
|
||||||
|
userMethod={userMethod}
|
||||||
|
devMethod={devMethod}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Tab.Panel>
|
</Tab.Panel>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import React, { ReactNode } from "react";
|
import React, { ReactNode, useState } from "react";
|
||||||
import { ParamType } from "@ethersproject/abi";
|
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 Uint256Decoder from "./Uint256Decoder";
|
||||||
import AddressDecoder from "./AddressDecoder";
|
import AddressDecoder from "./AddressDecoder";
|
||||||
import BooleanDecoder from "./BooleanDecoder";
|
import BooleanDecoder from "./BooleanDecoder";
|
||||||
|
@ -13,6 +17,7 @@ type DecodedParamRowProps = {
|
||||||
paramType: ParamType;
|
paramType: ParamType;
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
arrayElem?: number | undefined;
|
arrayElem?: number | undefined;
|
||||||
|
help?: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DecodedParamRow: React.FC<DecodedParamRowProps> = ({
|
const DecodedParamRow: React.FC<DecodedParamRowProps> = ({
|
||||||
|
@ -22,71 +27,95 @@ const DecodedParamRow: React.FC<DecodedParamRowProps> = ({
|
||||||
paramType,
|
paramType,
|
||||||
txData,
|
txData,
|
||||||
arrayElem,
|
arrayElem,
|
||||||
}) => (
|
help,
|
||||||
<>
|
}) => {
|
||||||
<tr className="grid grid-cols-12 gap-x-2 py-2 hover:bg-gray-100">
|
const [showHelp, setShowHelp] = useState<boolean>(false);
|
||||||
<td className="col-span-3 pl-1">
|
|
||||||
{prefix && <span className="text-gray-300">{prefix}</span>}
|
return (
|
||||||
{arrayElem !== undefined ? (
|
<>
|
||||||
<span className="text-gray-400">
|
<tr className="grid grid-cols-12 gap-x-2 py-2 hover:bg-gray-100">
|
||||||
{" "}
|
<td className="col-span-3 pl-1">
|
||||||
[<span className="text-black">{arrayElem}</span>]
|
<div>
|
||||||
</span>
|
{prefix && <span className="text-gray-300">{prefix}</span>}
|
||||||
) : (
|
{arrayElem !== undefined ? (
|
||||||
<>
|
<span className="text-gray-400">
|
||||||
{paramType.name ?? <span className="italic">param_{i}</span>}{" "}
|
{" "}
|
||||||
{i !== undefined && (
|
[<span className="text-black">{arrayElem}</span>]
|
||||||
<span className="text-gray-400 text-xs">({i})</span>
|
</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 + "."
|
|
||||||
) : (
|
) : (
|
||||||
<span className="italic">param_{i}.</span>
|
<>
|
||||||
)
|
{paramType.name ?? <span className="italic">param_{i}</span>}{" "}
|
||||||
}
|
{i !== undefined && (
|
||||||
i={idx}
|
<span className="text-gray-400 text-xs">({i})</span>
|
||||||
r={e}
|
)}
|
||||||
paramType={paramType.components[idx]}
|
</>
|
||||||
txData={txData}
|
)}
|
||||||
/>
|
{help && (
|
||||||
))}
|
<>
|
||||||
{paramType.baseType === "array" &&
|
{" "}
|
||||||
r.map((e: any, idx: number) => (
|
<Switch
|
||||||
<DecodedParamRow
|
checked={showHelp}
|
||||||
key={idx}
|
onChange={setShowHelp}
|
||||||
prefix={paramType.name ?? <span className="italic">param_{i}</span>}
|
className="text-gray-500"
|
||||||
r={e}
|
>
|
||||||
paramType={paramType.arrayChildren}
|
<FontAwesomeIcon
|
||||||
txData={txData}
|
icon={showHelp ? faQuestionCircleSolid : faQuestionCircle}
|
||||||
arrayElem={idx}
|
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);
|
export default React.memo(DecodedParamRow);
|
||||||
|
|
|
@ -2,12 +2,15 @@ import React from "react";
|
||||||
import { ParamType, Result } from "@ethersproject/abi";
|
import { ParamType, Result } from "@ethersproject/abi";
|
||||||
import DecodedParamRow from "./DecodedParamRow";
|
import DecodedParamRow from "./DecodedParamRow";
|
||||||
import { TransactionData } from "../../types";
|
import { TransactionData } from "../../types";
|
||||||
|
import { DevMethod, UserMethod } from "../../useSourcify";
|
||||||
|
|
||||||
type DecodedParamsTableProps = {
|
type DecodedParamsTableProps = {
|
||||||
args: Result;
|
args: Result;
|
||||||
paramTypes: ParamType[];
|
paramTypes: ParamType[];
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
hasParamNames?: boolean;
|
hasParamNames?: boolean;
|
||||||
|
userMethod?: UserMethod | undefined;
|
||||||
|
devMethod?: DevMethod | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DecodedParamsTable: React.FC<DecodedParamsTableProps> = ({
|
const DecodedParamsTable: React.FC<DecodedParamsTableProps> = ({
|
||||||
|
@ -15,6 +18,7 @@ const DecodedParamsTable: React.FC<DecodedParamsTableProps> = ({
|
||||||
paramTypes,
|
paramTypes,
|
||||||
txData,
|
txData,
|
||||||
hasParamNames = true,
|
hasParamNames = true,
|
||||||
|
devMethod,
|
||||||
}) => (
|
}) => (
|
||||||
<table className="border w-full">
|
<table className="border w-full">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -43,6 +47,7 @@ const DecodedParamsTable: React.FC<DecodedParamsTableProps> = ({
|
||||||
r={r}
|
r={r}
|
||||||
paramType={paramTypes[i]}
|
paramType={paramTypes[i]}
|
||||||
txData={txData}
|
txData={txData}
|
||||||
|
help={devMethod?.params?.[paramTypes[i].name]}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -3,6 +3,33 @@ import { Interface } from "@ethersproject/abi";
|
||||||
import { TransactionData } from "./types";
|
import { TransactionData } from "./types";
|
||||||
import { sourcifyMetadata, SourcifySource, sourcifySourceFile } from "./url";
|
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 = {
|
export type Metadata = {
|
||||||
version: string;
|
version: string;
|
||||||
language: string;
|
language: string;
|
||||||
|
@ -33,8 +60,8 @@ export type Metadata = {
|
||||||
};
|
};
|
||||||
output: {
|
output: {
|
||||||
abi: any[];
|
abi: any[];
|
||||||
userdocs: any[];
|
userdoc?: UserDoc | undefined;
|
||||||
devdoc: any[];
|
devdoc?: DevDoc | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue