diff --git a/components/forms/CreateTxForm/MsgForm/MsgRedelegateForm.tsx b/components/forms/CreateTxForm/MsgForm/MsgRedelegateForm.tsx new file mode 100644 index 0000000..d0c974f --- /dev/null +++ b/components/forms/CreateTxForm/MsgForm/MsgRedelegateForm.tsx @@ -0,0 +1,126 @@ +import { Decimal } from "@cosmjs/math"; +import { assert } from "@cosmjs/utils"; +import { Dispatch, SetStateAction, useCallback, useEffect, useState } from "react"; +import { useAppContext } from "../../../../context/AppContext"; +import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers"; +import { TxMsg, TxMsgRedelegate } from "../../../../types/txMsg"; +import Input from "../../../inputs/Input"; + +interface MsgRedelegateFormProps { + readonly delegatorAddress: string; + readonly setCheckAndGetMsg: Dispatch TxMsg | null) | undefined>>; +} + +const MsgRedelegateForm = ({ delegatorAddress, setCheckAndGetMsg }: MsgRedelegateFormProps) => { + const { state } = useAppContext(); + assert(state.chain.addressPrefix, "addressPrefix missing"); + + const [validatorSrcAddress, setValidatorSrcAddress] = useState(""); + const [validatorDstAddress, setValidatorDstAddress] = useState(""); + const [amount, setAmount] = useState("0"); + + const [validatorSrcAddressError, setValidatorSrcAddressError] = useState(""); + const [validatorDstAddressError, setValidatorDstAddressError] = useState(""); + const [amountError, setAmountError] = useState(""); + + const checkAndGetMsg = useCallback(() => { + assert(state.chain.addressPrefix, "addressPrefix missing"); + assert(state.chain.denom, "denom missing"); + + const srcAddressErrorMsg = checkAddress(validatorSrcAddress, state.chain.addressPrefix); + if (srcAddressErrorMsg) { + setValidatorSrcAddressError( + `Invalid address for network ${state.chain.chainId}: ${srcAddressErrorMsg}`, + ); + return null; + } + + const dstAddressErrorMsg = checkAddress(validatorDstAddress, state.chain.addressPrefix); + if (dstAddressErrorMsg) { + setValidatorDstAddressError( + `Invalid address for network ${state.chain.chainId}: ${dstAddressErrorMsg}`, + ); + return null; + } + + if (!amount || Number(amount) <= 0) { + setAmountError("Amount must be greater than 0"); + return null; + } + + const amountInAtomics = Decimal.fromUserInput( + amount, + Number(state.chain.displayDenomExponent), + ).atomics; + + const msg: TxMsgRedelegate = { + typeUrl: "/cosmos.staking.v1beta1.MsgBeginRedelegate", + value: { + delegatorAddress, + validatorSrcAddress, + validatorDstAddress, + amount: [{ amount: amountInAtomics, denom: state.chain.denom }], + }, + }; + + return msg; + }, [ + amount, + delegatorAddress, + state.chain.addressPrefix, + state.chain.chainId, + state.chain.denom, + state.chain.displayDenomExponent, + validatorDstAddress, + validatorSrcAddress, + ]); + + useEffect(() => { + setCheckAndGetMsg(() => checkAndGetMsg); + }, [checkAndGetMsg, setCheckAndGetMsg]); + + return ( + <> +
+ setValidatorSrcAddress(target.value)} + error={validatorSrcAddressError} + placeholder={`E.g. ${exampleAddress(0, state.chain.addressPrefix)}`} + /> +
+
+ setValidatorDstAddress(target.value)} + error={validatorDstAddressError} + placeholder={`E.g. ${exampleAddress(0, state.chain.addressPrefix)}`} + /> +
+
+ setAmount(target.value)} + error={amountError} + /> +
+ + + ); +}; + +export default MsgRedelegateForm;