Skip to content

Commit

Permalink
feat(website): tuples as json (read-only) and render each input for t…
Browse files Browse the repository at this point in the history
…uples in write mode (#873)
  • Loading branch information
Ignusmart authored Apr 12, 2024
1 parent 9183ebc commit 60e87e5
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 27 deletions.
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"next": "^13.4.19",
"pako": "^2.1.0",
"react": "18.2.0",
"react-code-blocks": "^0.1.6",
"react-diff-view": "^3.1.0",
"react-dom": "18.2.0",
"react-feather": "^2.0.10",
Expand Down
72 changes: 46 additions & 26 deletions packages/website/src/features/Deploy/DisplayedTransaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
FormLabel,
Input,
} from '@chakra-ui/react';
import { CopyBlock, a11yDark } from 'react-code-blocks';
import {
Address,
bytesToString,
Expand Down Expand Up @@ -103,6 +104,47 @@ export function DisplayedTransaction(props: {
return val.toString();
}

function renderInput(type: string, val: string): React.ReactElement {
if (type === 'tuple') {
return (
<CopyBlock
text={JSON.stringify(JSON.parse(encodeArg(type, val || '')), null, 2)}
language="json"
showLineNumbers={false}
codeBlock
theme={a11yDark}
customStyle={{ fontSize: '14px' }}
/>
);
}

return (
<Input
type="text"
size="sm"
bg="black"
borderColor="whiteAlpha.400"
isReadOnly
_focus={{
boxShadow: 'none !important',
outline: 'none !important',
borderColor: 'whiteAlpha.400 !important',
}}
_focusVisible={{
boxShadow: 'none !important',
outline: 'none !important',
borderColor: 'whiteAlpha.400 !important',
}}
_hover={{
boxShadow: 'none !important',
outline: 'none !important',
borderColor: 'whiteAlpha.400 !important',
}}
value={encodeArg(type, (val as string) || '')}
/>
);
}

if (!props.contracts) {
return <Text>{props.txn?.data}</Text>;
}
Expand Down Expand Up @@ -140,32 +182,10 @@ export function DisplayedTransaction(props: {
</Text>
)}
</FormLabel>
<Input
type="text"
size="sm"
bg="black"
borderColor="whiteAlpha.400"
isReadOnly
_focus={{
boxShadow: 'none !important',
outline: 'none !important',
borderColor: 'whiteAlpha.400 !important',
}}
_focusVisible={{
boxShadow: 'none !important',
outline: 'none !important',
borderColor: 'whiteAlpha.400 !important',
}}
_hover={{
boxShadow: 'none !important',
outline: 'none !important',
borderColor: 'whiteAlpha.400 !important',
}}
value={encodeArg(
execFuncFragment.inputs[i].type,
(execFuncArgs[i] as string) || ''
)}
/>
{renderInput(
execFuncFragment.inputs[i].type,
execFuncArgs[i]
)}
</FormControl>
</Box>,
])}
Expand Down
1 change: 1 addition & 0 deletions packages/website/src/features/Packages/Function.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const Function: FC<{
const [simulated, setSimulated] = useState(false);
const [error, setError] = useState<any>(null);
const [params, setParams] = useState<any[] | any>([]);

const { isConnected, address: from, chain: connectedChain } = useAccount();
const { openConnectModal } = useConnectModal();
const publicClient = usePublicClient({
Expand Down
6 changes: 5 additions & 1 deletion packages/website/src/features/Packages/FunctionInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AddressInput } from '@/features/Packages/FunctionInput/AddressInput';
import { NumberInput } from '@/features/Packages/FunctionInput/NumberInput';
import { DefaultInput } from '@/features/Packages/FunctionInput/DefaultInput';
import { AddIcon, CloseIcon } from '@chakra-ui/icons';
import TupleInput from './FunctionInput/TupleInput';

export const FunctionInput: FC<{
input: AbiParameter;
Expand All @@ -32,8 +33,9 @@ export const FunctionInput: FC<{
};

useEffect(() => {
if (!isArray) return;
valueUpdated(dataArray.map((item) => item.val));
}, [dataArray]);
}, [dataArray, isArray]);

const handleUpdate = (index: number | null, value: any) => {
if (isArray) {
Expand All @@ -53,6 +55,8 @@ export const FunctionInput: FC<{
return <AddressInput handleUpdate={_handleUpdate} />;
case input.type.startsWith('int') || input.type.startsWith('uint'):
return <NumberInput handleUpdate={_handleUpdate} />;
case input.type === 'tuple':
return <TupleInput input={input} handleUpdate={_handleUpdate} />;
default:
return (
<DefaultInput handleUpdate={_handleUpdate} inputType={input.type} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Flex, FormControl, FormLabel, Text } from '@chakra-ui/react';
import { FunctionInput } from '../FunctionInput';
import { useState } from 'react';
import { BigNumber } from 'ethers';
import { AbiParameter } from 'viem';

const TupleInput = ({
input,
handleUpdate,
}: {
input: any;
handleUpdate: (value: any) => void;
}) => {
const getDefaultValueForType = (component: AbiParameter) => {
if (component.type.startsWith('bool')) return false;
if (component.type.startsWith('int')) return '0';
if (component.type.startsWith('uint')) return '0';
return '';
};
// Initialize the tuple state as an object, with keys corresponding to tuple property names
const [tupleState, setTupleState] = useState(() =>
input.components.reduce((acc: any, component: any) => {
acc[component.name] = getDefaultValueForType(component);
return acc;
}, {})
);

const updateTupleValue = (name: string, value: any) => {
const updatedTupleState = { ...tupleState, [name]: value };
setTupleState(updatedTupleState);
handleUpdate(updatedTupleState); // Pass the entire tuple object up
};

return (
<Flex
borderLeft="1px"
borderColor="gray.600"
pl="4"
direction="column"
w="100%"
>
{input.components.map((component: any, index: number) => (
<FormControl mb="4" key={index}>
<FormLabel fontSize="sm" mb={1}>
{component.name && <Text display="inline">{component.name}</Text>}
{component.type && (
<Text fontSize="xs" color="whiteAlpha.700" display="inline">
{' '}
{component.type}
</Text>
)}
</FormLabel>
<FunctionInput
input={component}
valueUpdated={(value) => {
// Since tuple components are represented as a JSON object,
// We represent the bigint type as a string
if (typeof value === 'bigint') {
value = BigNumber.from(value).toString();
}
updateTupleValue(component.name, value);
}}
/>
</FormControl>
))}
</Flex>
);
};

export default TupleInput;

0 comments on commit 60e87e5

Please sign in to comment.