import { useBalanceFormat } from '@gear-js/react-hooks'; import { Button, Input } from '@gear-js/ui'; import { HexString } from '@polkadot/util/types'; import { zodResolver } from '@hookform/resolvers/zod'; import { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { Sails } from 'sails-js'; import { z } from 'zod'; import sendSVG from '@/shared/assets/images/actions/send.svg?react'; import { ValueField } from '@/shared/ui/form'; import { Box } from '@/shared/ui/box'; import { BackButton } from '@/shared/ui/backButton'; import { GasMethod } from '@/shared/config'; import { GasField } from '@/features/gasField'; import { useBalanceSchema, useGasCalculate, useGasLimitSchema, useMessageActions } from '@/hooks'; import { Result } from '@/hooks/useGasCalculate/types'; import { ProgramVoucherSelect } from '@/features/voucher'; import { LabeledCheckbox } from '@/shared/ui'; import { PayloadForm, getResetPayloadValue, useService, PayloadValue, PayloadValueSchema } from '@/features/sails'; import styles from './message-form.module.scss'; type Props = { id: HexString; programId: HexString | undefined; isReply: boolean; sails: Sails; }; const DEFAULT_VALUES = { value: '0', gasLimit: '0', voucherId: '', keepAlive: true, }; type Values = { value: string; gasLimit: string; voucherId: string; keepAlive: boolean; payload: PayloadValue; }; const useSchema = (payloadSchema: PayloadValueSchema) => { const balanceSchema = useBalanceSchema(); const gasLimitSchema = useGasLimitSchema(); return z.object({ payload: payloadSchema, value: balanceSchema, gasLimit: gasLimitSchema, keepAlive: z.boolean(), voucherId: z.string().trim(), }); }; type FormattedValues = z.infer>; const SailsMessageForm = ({ id, programId, isReply, sails }: Props) => { const { getFormattedGasValue } = useBalanceFormat(); const service = useService(sails, 'functions'); const defaultValues = { ...DEFAULT_VALUES, payload: service.defaultValues }; const schema = useSchema(service.schema); const form = useForm({ values: defaultValues, resolver: zodResolver(schema) }); const calculateGas = useGasCalculate(); const { sendMessage, replyMessage } = useMessageActions(); const [isDisabled, setIsDisabled] = useState(false); const [isGasDisabled, setIsGasDisabled] = useState(false); const [gasInfo, setGasInfo] = useState(); const method = isReply ? GasMethod.Reply : GasMethod.Handle; const disableSubmitButton = () => setIsDisabled(true); const enableSubmitButton = () => setIsDisabled(false); const resetForm = () => { const values = form.getValues(); const resetValue = { ...DEFAULT_VALUES, payload: getResetPayloadValue(values.payload) }; form.reset(resetValue); enableSubmitButton(); setGasInfo(undefined); }; const handleSubmitForm = form.handleSubmit(({ voucherId, ...values }) => { disableSubmitButton(); const payloadType = 'Bytes'; const reject = enableSubmitButton; const resolve = resetForm; if (isReply) return replyMessage({ reply: { ...values, replyToId: id }, payloadType, voucherId, reject, resolve }); sendMessage({ message: { ...values, destination: id }, payloadType, voucherId, reject, resolve }); }); const handleGasCalculate = () => { setIsGasDisabled(true); const values = form.getValues(); calculateGas(method, schema.parse(values), null, undefined, id) .then((info) => { const limit = getFormattedGasValue(info.limit).toFixed(); form.setValue('gasLimit', limit, { shouldValidate: true }); setGasInfo(info); }) .finally(() => setIsGasDisabled(false)); }; return (