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

#251 Add ABI encoding for raw input form #256

Merged
merged 40 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
799fc4d
test(apps/web): Pass json_abi specifications to raw input form
nevendyulgerov Oct 4, 2024
0a6df07
test(apps/web): Add abi option for raw input form
nevendyulgerov Oct 4, 2024
072916c
test(apps/web): Extend abi option for raw input form
nevendyulgerov Oct 8, 2024
79fd896
test(apps/web): Create GenericInputForm component
nevendyulgerov Oct 8, 2024
def4d28
test(apps/web): Extend GenericInputForm component
nevendyulgerov Oct 8, 2024
e0a6ec9
test(apps/web): Extend GenericInputForm component
nevendyulgerov Oct 9, 2024
12abe65
test(apps/web): Extend GenericInputForm component
nevendyulgerov Oct 9, 2024
ed9cb2b
chore(apps/web): Refactoring
nevendyulgerov Oct 9, 2024
eaac6b7
chore(apps/web): Refactoring
nevendyulgerov Oct 9, 2024
4052f90
chore(apps/web): Refactoring
nevendyulgerov Oct 9, 2024
3714508
feat(apps/web): Add fields for 'new' abi method
nevendyulgerov Oct 10, 2024
0436037
chore(apps/web): Refactoring
nevendyulgerov Oct 10, 2024
9e16e5a
chore(apps/web): Refactoring
nevendyulgerov Oct 10, 2024
4408c25
feat(apps/web): Add handling for abi params
nevendyulgerov Oct 11, 2024
3c77906
chore(apps/web): Refactoring
nevendyulgerov Oct 11, 2024
adcf833
chore(apps/web): Refactoring
nevendyulgerov Oct 13, 2024
051e01d
test(apps/web): Add unit tests for GenericInput form
nevendyulgerov Oct 14, 2024
e28f1dd
chore(apps/web): Cleanup
nevendyulgerov Oct 14, 2024
e0a6c74
chore(apps/web): Cleanup
nevendyulgerov Oct 14, 2024
555e332
feat(apps/web): Add hex input for raw value
nevendyulgerov Oct 29, 2024
5cedeed
feat(apps/web): Fix payload generation for json_abi
nevendyulgerov Oct 29, 2024
3434f6d
chore(packages/ui): Remove obsolete component
nevendyulgerov Oct 29, 2024
16253de
chore(packages/ui): Refactoring
nevendyulgerov Oct 29, 2024
6eea6f8
test(packages/ui): Fix test error
nevendyulgerov Oct 29, 2024
81627ea
feat(packages/ui): Add component for rendering nested tuple inputs
nevendyulgerov Nov 6, 2024
31599a1
chore(packages/ui): Refactoring
nevendyulgerov Nov 6, 2024
0f435b6
feat(packages/ui): Handle tuple params
nevendyulgerov Nov 7, 2024
f9c1887
fix(packages/ui): Fix validation issue with abi params
nevendyulgerov Nov 7, 2024
a3ad9a4
chore(packages/ui): Refactoring
nevendyulgerov Nov 7, 2024
8b02e62
chore(packages/ui): Refactoring
nevendyulgerov Nov 7, 2024
ce1e83a
chore(packages/ui): Cleanup
nevendyulgerov Nov 7, 2024
6555f43
test(apps/web): Keep application value after resetting the form
nevendyulgerov Nov 13, 2024
8f501f9
test(apps/web): Clear param errors when resetting the params
nevendyulgerov Nov 13, 2024
1e0a7a5
test(apps/web): Add index offset for params before tuples
nevendyulgerov Nov 13, 2024
b2b7484
test(apps/web): Tweak layout for tuple inputs
nevendyulgerov Nov 13, 2024
d1f1f33
feat(packages/ui): Reset abi function params when changing json abi v…
nevendyulgerov Nov 18, 2024
4592f99
feat(packages/ui): Extend handling for tuple params
nevendyulgerov Nov 19, 2024
d973035
chore(packages/ui): Refactoring
nevendyulgerov Nov 19, 2024
bdb550b
fix(packages/ui): Fix setting of abi function params
nevendyulgerov Nov 19, 2024
2f746db
chore(packages/ui): Refactoring
nevendyulgerov Nov 25, 2024
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
15 changes: 12 additions & 3 deletions apps/web/src/components/sendTransaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
ERC20DepositForm,
ERC721DepositForm,
EtherDepositForm,
RawInputForm,
GenericInputForm,
GenericInputFormSpecification,
TransactionFormSuccessData,
} from "@cartesi/rollups-explorer-ui";
import { Select } from "@mantine/core";
Expand All @@ -17,6 +18,8 @@ import { useSearchMultiTokens } from "../hooks/useSearchMultiTokens";
import { useSearchTokens } from "../hooks/useSearchTokens";
import getConfiguredChainId from "../lib/getConfiguredChain";
import { BlockExplorerLink } from "./BlockExplorerLink";
import { useSpecification } from "./specification/hooks/useSpecification";
import { JSON_ABI } from "./specification/types";

export type DepositType =
| "ether"
Expand Down Expand Up @@ -63,6 +66,9 @@ const SendTransaction: FC<DepositProps> = ({
address: debouncedMultiTokenId,
chainId,
});
const { listSpecifications } = useSpecification();
const specifications =
listSpecifications()?.filter((s) => s.mode === JSON_ABI) ?? [];

const onSuccess = useCallback(
({ receipt, type }: TransactionFormSuccessData) => {
Expand Down Expand Up @@ -120,7 +126,7 @@ const SendTransaction: FC<DepositProps> = ({
},
{
group: "Other",
items: [{ value: "input", label: "Raw Input" }],
items: [{ value: "input", label: "Generic Input" }],
},
]}
value={depositType}
Expand Down Expand Up @@ -154,8 +160,11 @@ const SendTransaction: FC<DepositProps> = ({
onSuccess={onSuccess}
/>
) : depositType === "input" ? (
<RawInputForm
<GenericInputForm
applications={applications}
specifications={
specifications as GenericInputFormSpecification[]
}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSuccess={onSuccess}
Expand Down
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"ramda-adjunct": "^5.0.1",
"react-icons": "^4",
"viem": "^2",
"uuid": "^11.0.3",
"wagmi": "^2"
},
"peerDependencies": {
Expand Down
156 changes: 156 additions & 0 deletions packages/ui/src/GenericInputForm/AbiFields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { useFormContext } from "./context";
import {
Flex,
Group,
SegmentedControl,
Select,
Text,
Textarea,
Tooltip,
} from "@mantine/core";
import { FC } from "react";
import { FormAbiMethod, FormSpecification, SpecificationMode } from "./types";
import { TbHelp } from "react-icons/tb";
import { AbiFunctionName } from "./AbiFunctionName";
import { AbiFunctionParams } from "./AbiFunctionParams";
import { AbiParameter } from "./AbiParameter";
import { resetAbiFunctionParams } from "./utils";

export interface AbiFieldsProps {
specifications: FormSpecification[];
}

export const AbiFields: FC<AbiFieldsProps> = ({ specifications }) => {
const form = useFormContext();
const { abiMethod, specificationMode } = form.getTransformedValues();
const specificationOptions = specifications.map((s) => ({
value: s.id,
label: s.name,
}));

return (
<>
<Select
label="ABI method"
description="Select how to attach an ABI"
data-testid="abi-method-select"
allowDeselect={false}
withAsterisk
data={[
{
value: "existing",
label: "ABI from an existing JSON_ABI specification",
},
{ value: "new", label: "New ABI" },
]}
{...form.getInputProps("abiMethod")}
onChange={(nextValue) => {
form.setFieldValue("abiMethod", nextValue as FormAbiMethod);
form.setFieldValue("specificationId", "");
form.setFieldValue("abiFunctionName", "");
form.setFieldValue("humanAbi", "");
form.setFieldValue("abiParam", "");
form.setFieldValue("savedAbiParam", "");
form.setFieldValue("specificationMode", "json_abi");
resetAbiFunctionParams(form, []);
}}
/>

{abiMethod === "new" ? (
<>
<SegmentedControl
aria-label="Specification Mode"
data={[
{
label: "JSON ABI",
value: "json_abi",
},
{
label: "ABI Parameters",
value: "abi_params",
},
]}
{...form.getInputProps("specificationMode")}
onChange={(nextValue) => {
form.setFieldValue(
"specificationMode",
nextValue as SpecificationMode,
);

form.setFieldValue("specificationId", "");
form.setFieldValue("abiFunctionName", "");
form.setFieldValue("humanAbi", "");
form.setFieldValue("abiParam", "");
form.setFieldValue("savedAbiParam", "");
resetAbiFunctionParams(form, []);
}}
/>

{specificationMode === "json_abi" ? (
<Textarea
data-testid="json-abi-textarea"
resize="vertical"
description="Define signatures in Human readable format"
placeholder="function balanceOf(address owner) view returns (uint256) event Transfer(address indexed from, address indexed to, uint256 amount)"
rows={5}
label={
<Group justify="flex-start" gap="3">
<Text size="sm">ABI</Text>
<Tooltip
multiline
label="Define the signature without wrapping it on quotes nor adding comma at the end to separate. Just hit enter and keep defining your signatures"
withArrow
w="300"
>
<Flex direction="column-reverse">
<TbHelp />
</Flex>
</Tooltip>
</Group>
}
{...form.getInputProps("humanAbi")}
onChange={(event) => {
const nextValue = event.target.value;
form.setFieldValue("humanAbi", nextValue);
form.validateField("humanAbi");
form.setFieldValue("abiFunctionName", "");
}}
/>
) : (
<AbiParameter />
)}
</>
) : (
<Select
label="Specifications"
description="Available JSON_ABI specifications"
placeholder="Select specification"
data={specificationOptions}
allowDeselect={false}
withAsterisk
{...form.getInputProps("specificationId")}
onChange={(nextValue) => {
form.setFieldValue(
"specificationId",
nextValue as string,
);
form.setFieldValue("abiFunctionName", "");
resetAbiFunctionParams(form, []);
}}
/>
)}

<AbiFunctionName />
<AbiFunctionParams />

<Textarea
label="Hex value"
description="Encoded hex value for the application"
readOnly
value={
form.isValid() ? form.getInputProps("rawInput").value : "0x"
}
/>
</>
);
};
124 changes: 124 additions & 0 deletions packages/ui/src/GenericInputForm/AbiFunctionName.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { useFormContext } from "./context";
import { Alert, Combobox, Input, InputBase, useCombobox } from "@mantine/core";
import { AbiFunction } from "viem";
import { useCallback } from "react";
import { FunctionSignature } from "./FunctionSignature";
import { TbAlertCircle } from "react-icons/tb";
import { resetAbiFunctionParams } from "./utils";
import { AbiInputParam, GenericFormAbiFunction } from "./types";

export const AbiFunctionName = () => {
const form = useFormContext();
const { abiMethod, abiFunction, selectedSpecification, specificationMode } =
form.getTransformedValues();
const combobox = useCombobox({
onDropdownClose: () => combobox.resetSelectedOption(),
});
const specificationFunctions = (
(selectedSpecification?.abi as GenericFormAbiFunction[]) ?? []
).filter((item) => item.type === "function");

const onChangeAbiFunctionName = useCallback(
(abiFunctionName: string) => {
combobox.closeDropdown();
form.setFieldValue("abiFunctionName", abiFunctionName);

const nextAbiFunction = (
(selectedSpecification?.abi as AbiFunction[]) ?? []
).find((abiFunction) => abiFunction.name === abiFunctionName);

if (nextAbiFunction) {
resetAbiFunctionParams(
form,
nextAbiFunction.inputs as AbiInputParam[],
);
}
},
[combobox, form, selectedSpecification],
);

return (
<>
{(abiMethod === "existing" || specificationMode === "json_abi") &&
selectedSpecification && (
<>
{specificationFunctions.length > 0 ? (
<Combobox
store={combobox}
onOptionSubmit={onChangeAbiFunctionName}
>
<Combobox.Target>
<InputBase
component="button"
type="button"
pointer
label="ABI Function"
description="Available ABI functions"
rightSection={<Combobox.Chevron />}
rightSectionPointerEvents="none"
withAsterisk
{...form.getInputProps(
"abiFunctionName",
)}
style={{ overflow: "hidden" }}
onClick={() =>
combobox.toggleDropdown()
}
>
{abiFunction ? (
<FunctionSignature
abiFunction={abiFunction}
/>
) : (
<Input.Placeholder>
Select function
</Input.Placeholder>
)}
</InputBase>
</Combobox.Target>

<Combobox.Dropdown>
<Combobox.Options>
{specificationFunctions.map(
(abiFunction) => {
const params =
abiFunction.inputs
.map(
(input) =>
`${input.type} ${input.name}`,
)
.join(", ");

return (
<Combobox.Option
key={`${abiFunction.name}-${params}`}
value={abiFunction.name}
>
<FunctionSignature
abiFunction={
abiFunction
}
/>
</Combobox.Option>
);
},
)}
</Combobox.Options>
</Combobox.Dropdown>
</Combobox>
) : (
<Alert
variant="light"
color="blue"
icon={<TbAlertCircle />}
data-testid="no-functions-alert"
>
No ABI functions available for this
specification.
</Alert>
)}
</>
)}
</>
);
};
Loading
Loading