import { Dispatch, SetStateAction, useEffect, useState } from "react"; import { ContractInput } from "./ContractInput"; import { getFunctionInputKey, getInitialTupleArrayFormState } from "./utilsContract"; import { replacer } from "~~/utils/scaffold-eth/common"; import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract"; type TupleArrayProps = { abiTupleParameter: AbiParameterTuple & { isVirtual?: true }; setParentForm: Dispatch>>; parentStateObjectKey: string; parentForm: Record | undefined; }; export const TupleArray = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleArrayProps) => { const [form, setForm] = useState>(() => getInitialTupleArrayFormState(abiTupleParameter)); const [additionalInputs, setAdditionalInputs] = useState>([ abiTupleParameter.components, ]); const depth = (abiTupleParameter.type.match(/\[\]/g) || []).length; useEffect(() => { // Extract and group fields based on index prefix const groupedFields = Object.keys(form).reduce( (acc, key) => { const [indexPrefix, ...restArray] = key.split("_"); const componentName = restArray.join("_"); if (!acc[indexPrefix]) { acc[indexPrefix] = {}; } acc[indexPrefix][componentName] = form[key]; return acc; }, {} as Record>, ); let argsArray: Array> = []; Object.keys(groupedFields).forEach(key => { const currentKeyValues = Object.values(groupedFields[key]); const argsStruct: Record = {}; abiTupleParameter.components.forEach((component, componentIndex) => { argsStruct[component.name || `input_${componentIndex}_`] = currentKeyValues[componentIndex]; }); argsArray.push(argsStruct); }); if (depth > 1) { argsArray = argsArray.map(args => { return args[abiTupleParameter.components[0].name || "tuple"]; }); } setParentForm(parentForm => { return { ...parentForm, [parentStateObjectKey]: JSON.stringify(argsArray, replacer) }; }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [JSON.stringify(form, replacer)]); const addInput = () => { setAdditionalInputs(previousValue => { const newAdditionalInputs = [...previousValue, abiTupleParameter.components]; // Add the new inputs to the form setForm(form => { const newForm = { ...form }; abiTupleParameter.components.forEach((component, componentIndex) => { const key = getFunctionInputKey( `${newAdditionalInputs.length - 1}_${abiTupleParameter.name || "tuple"}`, component, componentIndex, ); newForm[key] = ""; }); return newForm; }); return newAdditionalInputs; }); }; const removeInput = () => { // Remove the last inputs from the form setForm(form => { const newForm = { ...form }; abiTupleParameter.components.forEach((component, componentIndex) => { const key = getFunctionInputKey( `${additionalInputs.length - 1}_${abiTupleParameter.name || "tuple"}`, component, componentIndex, ); delete newForm[key]; }); return newForm; }); setAdditionalInputs(inputs => inputs.slice(0, -1)); }; return (

{abiTupleParameter.internalType}

{additionalInputs.map((additionalInput, additionalIndex) => (
{depth > 1 ? `${additionalIndex}` : `tuple[${additionalIndex}]`}
{additionalInput.map((param, index) => { const key = getFunctionInputKey( `${additionalIndex}_${abiTupleParameter.name || "tuple"}`, param, index, ); return ( ); })}
))}
{additionalInputs.length > 0 && ( )}
); };