Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show inherited functions in Debug (when deploying with hardhat) #564

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
64cd68d
WIP: it's working but it's ugly
FilipHarald Oct 9, 2023
c2fc773
chore: clean up code
FilipHarald Oct 9, 2023
05fc4e2
WIP: working on tooltip
FilipHarald Oct 9, 2023
60306a9
fix: added undefined-check
FilipHarald Oct 10, 2023
d021832
feat: added origin for read-functions
FilipHarald Oct 10, 2023
89b5d0d
feat: added tooltip to variables
FilipHarald Oct 10, 2023
935cb45
feat: improved tooltip
FilipHarald Oct 10, 2023
52fb827
feat: extracted to one component, changed to inherited from and now use
FilipHarald Oct 11, 2023
d121d8f
Merge branch 'main' into feat/contract_function_origins
technophile-04 Oct 15, 2023
e61b405
Merge branch 'main' of github.com:scaffold-eth/scaffold-eth-2 into fe…
FilipHarald Oct 23, 2023
18aa9b3
fix: rename InheritanceTip to InheritanceTooltip
FilipHarald Oct 23, 2023
7f9ef37
fix: implicit return instead
FilipHarald Oct 23, 2023
92aa41f
feat: cursor-help on tooltip
FilipHarald Oct 23, 2023
365e56d
feat: added InformationCircleIcon
FilipHarald Oct 23, 2023
32d5d23
feat: change background for variables-tooltip
FilipHarald Oct 23, 2023
4d98920
fix: correct type
FilipHarald Oct 23, 2023
e41ffaa
feat: changed sorting to before rendering
FilipHarald Oct 23, 2023
87d8b01
fix: change InheritedFunctions to optional
FilipHarald Oct 23, 2023
aa07342
feat: better tooltip color
FilipHarald Oct 23, 2023
3f1cb8f
Update packages/nextjs/components/scaffold-eth/Contract/InheritanceTo…
FilipHarald Oct 26, 2023
a4e3e42
fix: improved tooltip design
FilipHarald Oct 26, 2023
f51102d
fix: tooltip styles
FilipHarald Oct 26, 2023
f60aea5
Merge branch 'main' into feat/contract_function_origins
technophile-04 Oct 26, 2023
7335e46
get contract sources from contract defination
technophile-04 Oct 27, 2023
ae8151c
fix:spelling mistake for function
technophile-04 Oct 28, 2023
3905f97
direct return without else
technophile-04 Oct 28, 2023
25bf161
Merge pull request #1 from scaffold-eth/fix/inherited-edge-case
FilipHarald Oct 30, 2023
69e683c
Merge branch 'main' of github.com:scaffold-eth/scaffold-eth-2 into fe…
FilipHarald Nov 3, 2023
c3683ee
fix: allow for empty inheritedFunctions in externalContracts
FilipHarald Nov 6, 2023
94e4d40
Merge branch 'main' into feat/contract_function_origins
technophile-04 Nov 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions packages/hardhat/deploy/99_generateTsAbis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import * as fs from "fs";
import prettier from "prettier";
import { DeployFunction } from "hardhat-deploy/types";

const DEPLOYMENTS_DIR = "./deployments";
const ARTIFACTS_DIR = "./artifacts";

function getDirectories(path: string) {
return fs
.readdirSync(path, { withFileTypes: true })
Expand All @@ -24,7 +27,22 @@ function getContractNames(path: string) {
.map(dirent => dirent.name.split(".")[0]);
}

const DEPLOYMENTS_DIR = "./deployments";
function getInheritedFunctions(sources: { [key: string]: any }, contractName: string) {
carletex marked this conversation as resolved.
Show resolved Hide resolved
const inheritedFunctions = {} as Record<string, any>;
technophile-04 marked this conversation as resolved.
Show resolved Hide resolved
for (const sourcePath of Object.keys(sources)) {
const sourceName = sourcePath.split("/").pop()?.split(".sol")[0];
if (sourceName === contractName) {
continue;
}
const { abi } = JSON.parse(fs.readFileSync(`${ARTIFACTS_DIR}/${sourcePath}/${sourceName}.json`).toString());
for (const functionAbi of abi) {
if (functionAbi.type === "function") {
inheritedFunctions[functionAbi.name] = sourcePath;
}
}
}
return inheritedFunctions;
}

function getContractDataFromDeployments() {
if (!fs.existsSync(DEPLOYMENTS_DIR)) {
Expand All @@ -35,10 +53,11 @@ function getContractDataFromDeployments() {
const chainId = fs.readFileSync(`${DEPLOYMENTS_DIR}/${chainName}/.chainId`).toString();
const contracts = {} as Record<string, any>;
for (const contractName of getContractNames(`${DEPLOYMENTS_DIR}/${chainName}`)) {
const { abi, address } = JSON.parse(
const { abi, address, metadata } = JSON.parse(
fs.readFileSync(`${DEPLOYMENTS_DIR}/${chainName}/${contractName}.json`).toString(),
);
contracts[contractName] = { address, abi };
const inheritedFunctions = getInheritedFunctions(JSON.parse(metadata).sources, contractName);
contracts[contractName] = { address, abi, inheritedFunctions };
}
output[chainId] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReadOnlyFunctionForm } from "./ReadOnlyFunctionForm";
import { Abi, AbiFunction } from "abitype";
import { Contract, ContractName } from "~~/utils/scaffold-eth/contract";
import { Contract, ContractName, InheritedFunctions } from "~~/utils/scaffold-eth/contract";

export const ContractReadMethods = ({ deployedContractData }: { deployedContractData: Contract<ContractName> }) => {
if (!deployedContractData) {
Expand All @@ -21,9 +21,16 @@ export const ContractReadMethods = ({ deployedContractData }: { deployedContract

return (
<>
{functionsToDisplay.map(fn => (
<ReadOnlyFunctionForm contractAddress={deployedContractData.address} abiFunction={fn} key={fn.name} />
))}
{functionsToDisplay
.map(fn => (
<ReadOnlyFunctionForm
contractAddress={deployedContractData.address}
abiFunction={fn}
key={fn.name}
inheritedBy={(deployedContractData.inheritedFunctions as InheritedFunctions)[fn.name]}
/>
))
.sort((a, b) => (b.props.inheritedBy ? b.props.inheritedBy.localeCompare(a.props.inheritedBy) : 1))}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DisplayVariable } from "./DisplayVariable";
import { Abi, AbiFunction } from "abitype";
import { Contract, ContractName } from "~~/utils/scaffold-eth/contract";
import { Contract, ContractName, InheritedFunctions } from "~~/utils/scaffold-eth/contract";

export const ContractVariables = ({
refreshDisplayVariables,
Expand All @@ -27,14 +27,17 @@ export const ContractVariables = ({

return (
<>
{functionsToDisplay.map(fn => (
<DisplayVariable
abiFunction={fn}
contractAddress={deployedContractData.address}
key={fn.name}
refreshDisplayVariables={refreshDisplayVariables}
/>
))}
{functionsToDisplay
.map(fn => (
<DisplayVariable
abiFunction={fn}
contractAddress={deployedContractData.address}
key={fn.name}
refreshDisplayVariables={refreshDisplayVariables}
inheritedBy={(deployedContractData.inheritedFunctions as InheritedFunctions)[fn.name]}
/>
))
.sort((a, b) => (b.props.inheritedBy ? b.props.inheritedBy.localeCompare(a.props.inheritedBy) : 1))}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { WriteOnlyFunctionForm } from "./WriteOnlyFunctionForm";
import { Abi, AbiFunction } from "abitype";
import { Contract, ContractName } from "~~/utils/scaffold-eth/contract";
import { Contract, ContractName, InheritedFunctions } from "~~/utils/scaffold-eth/contract";

export const ContractWriteMethods = ({
onChange,
Expand All @@ -26,14 +26,17 @@ export const ContractWriteMethods = ({

return (
<>
{functionsToDisplay.map((fn, idx) => (
<WriteOnlyFunctionForm
key={`${fn.name}-${idx}}`}
abiFunction={fn}
onChange={onChange}
contractAddress={deployedContractData.address}
/>
))}
{functionsToDisplay
.map((fn, idx) => (
<WriteOnlyFunctionForm
key={`${fn.name}-${idx}}`}
abiFunction={fn}
onChange={onChange}
contractAddress={deployedContractData.address}
inheritedBy={(deployedContractData.inheritedFunctions as InheritedFunctions)[fn.name]}
/>
))
.sort((a, b) => (b.props.inheritedBy ? b.props.inheritedBy.localeCompare(a.props.inheritedBy) : 1))}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ type DisplayVariableProps = {
contractAddress: Address;
abiFunction: AbiFunction;
refreshDisplayVariables: boolean;
inheritedBy?: string;
};

export const DisplayVariable = ({ contractAddress, abiFunction, refreshDisplayVariables }: DisplayVariableProps) => {
export const DisplayVariable = ({
contractAddress,
abiFunction,
refreshDisplayVariables,
inheritedBy,
}: DisplayVariableProps) => {
const {
data: result,
isFetching,
Expand All @@ -36,7 +42,20 @@ export const DisplayVariable = ({ contractAddress, abiFunction, refreshDisplayVa
return (
<div className="space-y-1 pb-2">
<div className="flex items-center gap-2">
<h3 className="font-medium text-lg mb-0 break-all">{abiFunction.name}</h3>
<h3 className="font-medium text-lg mb-0 break-all">
{abiFunction.name}
{inheritedBy && (
<span className="has-tooltip p-2">
<span>*</span>
<span className="nested-tooltip bg-secondary rounded p-3 m-2">
Inherited by:{" "}
carletex marked this conversation as resolved.
Show resolved Hide resolved
<code className="italic bg-base-300 text-base font-bold break-words break-all inline-block">
{inheritedBy}
</code>
</span>
</span>
)}
</h3>
<button className="btn btn-ghost btn-xs" onClick={async () => await refetch()}>
{isFetching ? (
<span className="loading loading-spinner loading-xs"></span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import { notification } from "~~/utils/scaffold-eth";
type TReadOnlyFunctionFormProps = {
contractAddress: Address;
abiFunction: AbiFunction;
inheritedBy?: string;
};

export const ReadOnlyFunctionForm = ({ contractAddress, abiFunction }: TReadOnlyFunctionFormProps) => {
export const ReadOnlyFunctionForm = ({ contractAddress, abiFunction, inheritedBy }: TReadOnlyFunctionFormProps) => {
const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
const [result, setResult] = useState<unknown>();

Expand Down Expand Up @@ -49,7 +50,20 @@ export const ReadOnlyFunctionForm = ({ contractAddress, abiFunction }: TReadOnly

return (
<div className="flex flex-col gap-3 py-5 first:pt-0 last:pb-1">
<p className="font-medium my-0 break-words">{abiFunction.name}</p>
<p className="font-medium my-0 break-words">
{abiFunction.name}
{inheritedBy && (
<span className="has-tooltip p-2">
<span>*</span>
<span className="nested-tooltip bg-secondary rounded p-3 m-2">
Inherited by:{" "}
<code className="italic bg-base-300 text-base font-bold break-words break-all inline-block">
{inheritedBy}
</code>
</span>
</span>
)}
</p>
{inputElements}
<div className="flex justify-between gap-2 flex-wrap">
<div className="flex-grow w-4/5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ type WriteOnlyFunctionFormProps = {
abiFunction: AbiFunction;
onChange: () => void;
contractAddress: Address;
inheritedBy?: string;
};

export const WriteOnlyFunctionForm = ({ abiFunction, onChange, contractAddress }: WriteOnlyFunctionFormProps) => {
export const WriteOnlyFunctionForm = ({
abiFunction,
onChange,
contractAddress,
inheritedBy,
}: WriteOnlyFunctionFormProps) => {
const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
const [txValue, setTxValue] = useState<string | bigint>("");
const { chain } = useNetwork();
Expand Down Expand Up @@ -81,7 +87,20 @@ export const WriteOnlyFunctionForm = ({ abiFunction, onChange, contractAddress }
return (
<div className="py-5 space-y-3 first:pt-0 last:pb-1">
<div className={`flex gap-3 ${zeroInputs ? "flex-row justify-between items-center" : "flex-col"}`}>
<p className="font-medium my-0 break-words">{abiFunction.name}</p>
<p className="font-medium my-0 break-words">
{abiFunction.name}{" "}
{inheritedBy && (
<span className="has-tooltip p-2">
<span>*</span>
<span className="nested-tooltip bg-secondary rounded p-3 m-2">
Inherited by:{" "}
<code className="italic bg-base-300 text-base font-bold break-words break-all inline-block">
{inheritedBy}
</code>
</span>
</span>
)}
</p>
{inputs}
{abiFunction.stateMutability === "payable" ? (
<IntegerInput
Expand Down
16 changes: 16 additions & 0 deletions packages/nextjs/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ module.exports = {
".tooltip": {
"--tooltip-tail": "6px",
},
".nested-tooltip": {
visibility: "hidden",
position: "absolute",
},
".has-tooltip:hover .nested-tooltip": {
visibility: "visible",
"z-index": "100",
},
carletex marked this conversation as resolved.
Show resolved Hide resolved
},
},
{
Expand Down Expand Up @@ -57,6 +65,14 @@ module.exports = {
"--tooltip-tail": "6px",
"--tooltip-color": "hsl(var(--p))",
},
".nested-tooltip": {
visibility: "hidden",
position: "absolute",
},
".has-tooltip:hover .nested-tooltip": {
visibility: "visible",
"z-index": "100",
},
},
},
{
Expand Down
3 changes: 3 additions & 0 deletions packages/nextjs/utils/scaffold-eth/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type Prettify<T> = {
[K in keyof T]: T[K];
} & unknown;

export type InheritedFunctions = { readonly [key: string]: string };

export type GenericContractsDeclaration = {
[key: number]: readonly {
name: string;
Expand All @@ -38,6 +40,7 @@ export type GenericContractsDeclaration = {
[key: string]: {
address: Address;
abi: Abi;
inheritedFunctions: InheritedFunctions;
};
};
}[];
Expand Down