Initial commit with 🏗️ Scaffold-ETH 2 @ 1.0.2
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { InheritanceTooltip } from "./InheritanceTooltip";
|
||||
import { Abi, AbiFunction } from "abitype";
|
||||
import { Address, TransactionReceipt } from "viem";
|
||||
import { useAccount, useConfig, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
|
||||
import {
|
||||
ContractInput,
|
||||
TxReceipt,
|
||||
getFunctionInputKey,
|
||||
getInitialFormState,
|
||||
getParsedContractFunctionArgs,
|
||||
transformAbiFunction,
|
||||
} from "~~/app/debug/_components/contract";
|
||||
import { IntegerInput } from "~~/components/scaffold-eth";
|
||||
import { useTransactor } from "~~/hooks/scaffold-eth";
|
||||
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
|
||||
import { simulateContractWriteAndNotifyError } from "~~/utils/scaffold-eth/contract";
|
||||
|
||||
type WriteOnlyFunctionFormProps = {
|
||||
abi: Abi;
|
||||
abiFunction: AbiFunction;
|
||||
onChange: () => void;
|
||||
contractAddress: Address;
|
||||
inheritedFrom?: string;
|
||||
};
|
||||
|
||||
export const WriteOnlyFunctionForm = ({
|
||||
abi,
|
||||
abiFunction,
|
||||
onChange,
|
||||
contractAddress,
|
||||
inheritedFrom,
|
||||
}: WriteOnlyFunctionFormProps) => {
|
||||
const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
|
||||
const [txValue, setTxValue] = useState<string>("");
|
||||
const { chain } = useAccount();
|
||||
const writeTxn = useTransactor();
|
||||
const { targetNetwork } = useTargetNetwork();
|
||||
const writeDisabled = !chain || chain?.id !== targetNetwork.id;
|
||||
|
||||
const { data: result, isPending, writeContractAsync } = useWriteContract();
|
||||
|
||||
const wagmiConfig = useConfig();
|
||||
|
||||
const handleWrite = async () => {
|
||||
if (writeContractAsync) {
|
||||
try {
|
||||
const writeContractObj = {
|
||||
address: contractAddress,
|
||||
functionName: abiFunction.name,
|
||||
abi: abi,
|
||||
args: getParsedContractFunctionArgs(form),
|
||||
value: BigInt(txValue),
|
||||
};
|
||||
await simulateContractWriteAndNotifyError({ wagmiConfig, writeContractParams: writeContractObj });
|
||||
|
||||
const makeWriteWithParams = () => writeContractAsync(writeContractObj);
|
||||
await writeTxn(makeWriteWithParams);
|
||||
onChange();
|
||||
} catch (e: any) {
|
||||
console.error("⚡️ ~ file: WriteOnlyFunctionForm.tsx:handleWrite ~ error", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const [displayedTxResult, setDisplayedTxResult] = useState<TransactionReceipt>();
|
||||
const { data: txResult } = useWaitForTransactionReceipt({
|
||||
hash: result,
|
||||
});
|
||||
useEffect(() => {
|
||||
setDisplayedTxResult(txResult);
|
||||
}, [txResult]);
|
||||
|
||||
// TODO use `useMemo` to optimize also update in ReadOnlyFunctionForm
|
||||
const transformedFunction = transformAbiFunction(abiFunction);
|
||||
const inputs = transformedFunction.inputs.map((input, inputIndex) => {
|
||||
const key = getFunctionInputKey(abiFunction.name, input, inputIndex);
|
||||
return (
|
||||
<ContractInput
|
||||
key={key}
|
||||
setForm={updatedFormValue => {
|
||||
setDisplayedTxResult(undefined);
|
||||
setForm(updatedFormValue);
|
||||
}}
|
||||
form={form}
|
||||
stateObjectKey={key}
|
||||
paramType={input}
|
||||
/>
|
||||
);
|
||||
});
|
||||
const zeroInputs = inputs.length === 0 && abiFunction.stateMutability !== "payable";
|
||||
|
||||
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}
|
||||
<InheritanceTooltip inheritedFrom={inheritedFrom} />
|
||||
</p>
|
||||
{inputs}
|
||||
{abiFunction.stateMutability === "payable" ? (
|
||||
<div className="flex flex-col gap-1.5 w-full">
|
||||
<div className="flex items-center ml-2">
|
||||
<span className="text-xs font-medium mr-2 leading-none">payable value</span>
|
||||
<span className="block text-xs font-extralight leading-none">wei</span>
|
||||
</div>
|
||||
<IntegerInput
|
||||
value={txValue}
|
||||
onChange={updatedTxValue => {
|
||||
setDisplayedTxResult(undefined);
|
||||
setTxValue(updatedTxValue);
|
||||
}}
|
||||
placeholder="value (wei)"
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex justify-between gap-2">
|
||||
{!zeroInputs && (
|
||||
<div className="grow basis-0">{displayedTxResult ? <TxReceipt txResult={displayedTxResult} /> : null}</div>
|
||||
)}
|
||||
<div
|
||||
className={`flex ${
|
||||
writeDisabled &&
|
||||
"tooltip tooltip-bottom tooltip-secondary before:content-[attr(data-tip)] before:-translate-x-1/3 before:left-auto before:transform-none"
|
||||
}`}
|
||||
data-tip={`${writeDisabled && "Wallet not connected or in the wrong network"}`}
|
||||
>
|
||||
<button className="btn btn-secondary btn-sm" disabled={writeDisabled || isPending} onClick={handleWrite}>
|
||||
{isPending && <span className="loading loading-spinner loading-xs"></span>}
|
||||
Send 💸
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{zeroInputs && txResult ? (
|
||||
<div className="grow basis-0">
|
||||
<TxReceipt txResult={txResult} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user