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

Feat/validate label #99

Merged
merged 6 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#99](https://github.com/alleslabs/celatone-frontend/pull/89) Validate label field in instantiate page
poomthiti marked this conversation as resolved.
Show resolved Hide resolved
- [#97](https://github.com/alleslabs/celatone-frontend/pull/97) Change label style to always afloat
- [#96](https://github.com/alleslabs/celatone-frontend/pull/96) Fix incorrect instantiated block height explorer link
- [#95](https://github.com/alleslabs/celatone-frontend/pull/95) Add network to url path
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/forms/ControllerInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ export const ControllerInput = <T extends FieldValues>({
});

const isError = !!error;
const isRequired = "required" in rules;
return (
<FormControl size={size} isInvalid={isError} {...componentProps} {...field}>
poomthiti marked this conversation as resolved.
Show resolved Hide resolved
{label && (
<FormLabel className={`${size}-label`} bgColor={labelBgColor}>
{label}
{label} {isRequired && <span style={{ color: "#EF5350" }}>*</span>}
poomthiti marked this conversation as resolved.
Show resolved Hide resolved
</FormLabel>
)}
<Input
Expand Down
94 changes: 60 additions & 34 deletions src/lib/pages/instantiate/instantiate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
useSimulateFee,
} from "lib/app-provider";
import { useInstantiateTx } from "lib/app-provider/tx/instantiate";
import { ControllerInput, TextInput } from "lib/components/forms";
import { ControllerInput } from "lib/components/forms";
import { AssetInput } from "lib/components/forms/AssetInput";
import JsonInput from "lib/components/json/JsonInput";
import { Stepper } from "lib/components/stepper";
Expand Down Expand Up @@ -62,15 +62,23 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
const [method, setMethod] = useState<"select-existing" | "fill-manually">(
"select-existing"
);
const [codeId, setCodeId] = useState("");
const [error, setError] = useState("");
const [simulateError, setSimulateError] = useState("");
poomthiti marked this conversation as resolved.
Show resolved Hide resolved
const [simulating, setSimulating] = useState(false);

// ------------------------------------------//
// ----------------FORM HOOKS----------------//
// ------------------------------------------//
const { control, setValue, watch, handleSubmit, reset } = useForm({
const {
control,
formState: { errors: formErrors },
setValue,
watch,
handleSubmit,
reset,
} = useForm({
mode: "all",
defaultValues: {
codeId: "",
label: "",
adminAddress: "",
initMsg: "",
Expand All @@ -81,13 +89,22 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
control,
name: "assets",
});
const watchAssets = watch("assets");
const watchInitMsg = watch("initMsg");
const [watchAssets, watchInitMsg, watchCodeId] = watch([
poomthiti marked this conversation as resolved.
Show resolved Hide resolved
"assets",
"initMsg",
"codeId",
]);

const selectedAssets = watchAssets.map((asset) => asset.denom);

const disableInstantiate = useMemo(() => {
return !codeId || !address || !!jsonValidate(watchInitMsg);
}, [codeId, address, watchInitMsg]);
return (
!watchCodeId ||
!address ||
!!jsonValidate(watchInitMsg) ||
!!formErrors.label
);
}, [watchCodeId, address, watchInitMsg, formErrors.label]);

const assetOptions = useMemo(
() =>
Expand All @@ -114,7 +131,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
const msg = composeMsg(MsgType.INSTANTIATE, {
sender: address as HumanAddr,
admin: adminAddress as HumanAddr,
codeId: Long.fromString(codeId),
codeId: Long.fromString(watchCodeId),
label,
msg: Buffer.from(initMsg),
funds,
Expand All @@ -123,7 +140,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
const estimatedFee = await simulate([msg]);
const stream = await postInstantiateTx({
estimatedFee: estimatedFee ? fabricateFee(estimatedFee) : undefined,
codeId: Number(codeId),
codeId: Number(watchCodeId),
initMsg: JSON.parse(initMsg),
label,
admin: adminAddress,
Expand All @@ -134,13 +151,13 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
if (stream) broadcast(stream);
setSimulating(false);
} catch (e) {
setError((e as Error).message);
setSimulateError((e as Error).message);
setSimulating(false);
}
})();
}, [
address,
codeId,
watchCodeId,
handleSubmit,
fabricateFee,
postInstantiateTx,
Expand All @@ -153,13 +170,13 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
// --------------SIDE EFFECTS----------------//
// ------------------------------------------//
useEffect(() => {
if (codeIdQuery) setCodeId(codeIdQuery);
if (codeIdQuery) setValue("codeId", codeIdQuery);
if (msgQuery) {
const decodedMsg = decode(msgQuery);
try {
const msgObject = JSON.parse(decodedMsg) as InstantiateRedoMsg;

setCodeId(String(msgObject.code_id));
setValue("codeId", String(msgObject.code_id));
reset({
label: msgObject.label,
adminAddress: msgObject.admin,
Expand All @@ -176,7 +193,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
// comment just to avoid eslint no-empty
}
}
}, [codeIdQuery, msgQuery, reset]);
}, [codeIdQuery, msgQuery, reset, setValue]);

return (
<>
Expand Down Expand Up @@ -204,31 +221,35 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
</Radio>
</Flex>
</RadioGroup>
{method === "select-existing" ? (
<CodeSelect
mt="16px"
mb="32px"
onCodeSelect={(code: string) => setCodeId(code)}
codeId={codeId}
/>
) : (
<TextInput
variant="floating"
label="Code ID"
helperText="Input existing Code ID manually"
my="32px"
value={codeId}
setInputState={setCodeId}
/>
)}
<form>
<form style={{ width: "100%" }}>
{method === "select-existing" ? (
<CodeSelect
mt="16px"
mb="32px"
onCodeSelect={(code: string) => setValue("codeId", code)}
codeId={watchCodeId}
/>
) : (
<ControllerInput
name="codeId"
control={control}
error={!watchCodeId ? formErrors.codeId?.message : undefined}
label="Code ID"
helperText="Input existing Code ID manually"
variant="floating"
my="32px"
rules={{ required: "Code ID is required" }}
/>
)}
<ControllerInput
name="label"
control={control}
error={formErrors.label?.message}
label="Label"
helperText="Label will help remind you or other contract viewer to understand what this contract do and how it works"
variant="floating"
mb="32px"
rules={{ required: "Label is required" }}
/>
<ControllerInput
name="adminAddress"
Expand Down Expand Up @@ -297,7 +318,12 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
disabled={disableInstantiate}
loading={simulating}
/>
{error && <FailedModal errorLog={error} onClose={() => setError("")} />}
{simulateError && (
<FailedModal
errorLog={simulateError}
onClose={() => setSimulateError("")}
/>
)}
</>
);
};
Expand Down