diff --git a/CHANGELOG.md b/CHANGELOG.md index 7411db9f8..1431bd8ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#524](https://github.com/alleslabs/celatone-frontend/pull/524) Add initia abi form - [#530](https://github.com/alleslabs/celatone-frontend/pull/530) Publish module component state wireup and add leaflet - [#521](https://github.com/alleslabs/celatone-frontend/pull/521) Initia module interaction function panel and selected function info accordion - [#515](https://github.com/alleslabs/celatone-frontend/pull/515) Initia select module drawer wireup diff --git a/package.json b/package.json index 063a62df2..92712f8dc 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@emotion/styled": "^11", "@graphql-codegen/cli": "^2.13.12", "@graphql-codegen/client-preset": "^1.1.4", + "@initia/initia.js": "^0.1.8", "@rjsf/chakra-ui": "v5.0.0-beta.10", "@rjsf/core": "v5.0.0-beta.10", "@rjsf/utils": "v5.0.0-beta.10", diff --git a/src/lib/app-provider/hooks/useAddress.ts b/src/lib/app-provider/hooks/useAddress.ts index b69e26a93..220475716 100644 --- a/src/lib/app-provider/hooks/useAddress.ts +++ b/src/lib/app-provider/hooks/useAddress.ts @@ -54,7 +54,7 @@ const validateAddress = ( getAddressTypeByLength: GetAddressTypeByLengthFn ) => { if (!bech32Prefix) - return "Can not retrieve bech32 prefix of the current network."; + return "Cannot retrieve bech32 prefix of the current network."; const prefix = getPrefix(bech32Prefix, addressType); diff --git a/src/lib/components/AddressInput.tsx b/src/lib/components/AddressInput.tsx index 630be8527..21b2886f5 100644 --- a/src/lib/components/AddressInput.tsx +++ b/src/lib/components/AddressInput.tsx @@ -67,7 +67,7 @@ export const AddressInput = ({ label={label} placeholder={placeholder ?? exampleUserAddress} type="text" - variant="floating" + variant="fixed-floating" status={status} labelBgColor={labelBgColor} helperText={helperText} diff --git a/src/lib/components/OffChainForm.tsx b/src/lib/components/OffChainForm.tsx index 3e3e42607..a56a333d0 100644 --- a/src/lib/components/OffChainForm.tsx +++ b/src/lib/components/OffChainForm.tsx @@ -46,7 +46,7 @@ export const OffChainForm = ({ label="Name" placeholder={contractLabel} helperText="Set name for your contract" - variant="floating" + variant="fixed-floating" rules={{ maxLength: constants.maxContractNameLength, }} @@ -60,7 +60,7 @@ export const OffChainForm = ({ control={control} label="Description" placeholder="Help understanding what this contract do and how it works ..." - variant="floating" + variant="fixed-floating" rules={{ maxLength: constants.maxContractDescriptionLength, }} diff --git a/src/lib/components/abi/AbiForm.tsx b/src/lib/components/abi/AbiForm.tsx new file mode 100644 index 000000000..cce57b23e --- /dev/null +++ b/src/lib/components/abi/AbiForm.tsx @@ -0,0 +1,53 @@ +import { Flex } from "@chakra-ui/react"; +import { useForm } from "react-hook-form"; + +import type { AbiFormData, ExposedFunction } from "lib/types"; + +import { ArgsForm } from "./args-form"; +import { TypesForm } from "./types-form"; + +interface AbiFormProps { + fn: ExposedFunction; + initialData: AbiFormData; + propsOnChange?: (data: AbiFormData) => void; + propsOnErrors?: (errors: [string, string][]) => void; +} + +export const AbiForm = ({ + fn, + initialData, + propsOnChange, + propsOnErrors, +}: AbiFormProps) => { + const { setValue, watch, getValues } = useForm({ + defaultValues: initialData, + mode: "all", + }); + const { typeArgs, args } = watch(); + + return ( + + {Object.keys(typeArgs).length > 0 && ( + { + setValue("typeArgs", value); + propsOnChange?.(getValues()); + }} + /> + )} + {Object.keys(args).length > 0 && ( + { + setValue("args", value); + propsOnChange?.(getValues()); + }} + propsOnErrors={propsOnErrors} + /> + )} + + ); +}; diff --git a/src/lib/components/abi/args-form/field/ArgFieldWidget.tsx b/src/lib/components/abi/args-form/field/ArgFieldWidget.tsx new file mode 100644 index 000000000..9182a5681 --- /dev/null +++ b/src/lib/components/abi/args-form/field/ArgFieldWidget.tsx @@ -0,0 +1,91 @@ +import { Input, Textarea } from "@chakra-ui/react"; +import { Select } from "chakra-react-select"; +import type { ControllerRenderProps } from "react-hook-form"; + +import type { Option } from "lib/types"; + +import { UintTypes } from "./utils"; + +const getInputPlaceholder = (type: string, isNull: boolean) => { + if (type === "0x1::string::String" && !isNull) + return "Left blank to send as empty string"; + if (type === "&signer") return "Signer is auto-filled when signing a tx"; + return " "; +}; + +const boolOptions = [ + { label: "True", value: "true" }, + { label: "False", value: "false" }, +]; + +interface ArgFieldWidgetProps { + type: string; + value: Option; + onChange: ControllerRenderProps["onChange"]; +} + +export const ArgFieldWidget = ({ + type, + value, + onChange, +}: ArgFieldWidgetProps) => { + if ( + UintTypes.includes(type) || + type === "address" || + type === "0x1::string::String" || + type === "&signer" + ) + return ( + + ); + + if (type === "bool") + return ( +