Tweak forms with trim and misc improvements
This commit is contained in:
parent
34b5cea418
commit
71bdbe6094
@ -2,7 +2,7 @@ import { MsgWithdrawDelegatorRewardEncodeObject } from "@cosmjs/stargate";
|
||||
import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -23,35 +23,38 @@ const MsgClaimRewardsForm = ({
|
||||
const [validatorAddress, setValidatorAddress] = useState("");
|
||||
const [validatorAddressError, setValidatorAddressError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ validatorAddress });
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { validatorAddress } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setValidatorAddressError("");
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
const addressErrorMsg = checkAddress(validatorAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setValidatorAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const addressErrorMsg = checkAddress(validatorAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setValidatorAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.WithdrawDelegatorReward].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorAddress,
|
||||
});
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.WithdrawDelegatorReward].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorAddress,
|
||||
});
|
||||
|
||||
const msg: MsgWithdrawDelegatorRewardEncodeObject = {
|
||||
typeUrl: MsgTypeUrls.WithdrawDelegatorReward,
|
||||
value: msgValue,
|
||||
};
|
||||
const msg: MsgWithdrawDelegatorRewardEncodeObject = {
|
||||
typeUrl: MsgTypeUrls.WithdrawDelegatorReward,
|
||||
value: msgValue,
|
||||
};
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
} catch {}
|
||||
}, [chain.addressPrefix, chain.chainId, delegatorAddress, setMsgGetter, validatorAddress]);
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [chain.addressPrefix, chain.chainId, delegatorAddress, setMsgGetter, trimmedInputs]);
|
||||
|
||||
return (
|
||||
<StackableContainer lessPadding lessMargin>
|
||||
@ -64,7 +67,10 @@ const MsgClaimRewardsForm = ({
|
||||
label="Validator Address"
|
||||
name="validator-address"
|
||||
value={validatorAddress}
|
||||
onChange={({ target }) => setValidatorAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setValidatorAddress(target.value);
|
||||
setValidatorAddressError("");
|
||||
}}
|
||||
error={validatorAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
import { EncodeObject } from "@cosmjs/proto-signing";
|
||||
import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import {
|
||||
datetimeLocalFromTimestamp,
|
||||
timestampFromDatetimeLocal,
|
||||
} from "../../../../lib/dateHelpers";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -36,60 +36,65 @@ const MsgCreateVestingAccountForm = ({
|
||||
const [amountError, setAmountError] = useState("");
|
||||
const [endTimeError, setEndTimeError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ toAddress, amount, endTime });
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { toAddress, amount, endTime } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setToAddressError("");
|
||||
setAmountError("");
|
||||
setEndTimeError("");
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
const addressErrorMsg = checkAddress(toAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setToAddressError(`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`);
|
||||
return false;
|
||||
}
|
||||
const addressErrorMsg = checkAddress(toAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setToAddressError(`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
const timeoutDate = new Date(timestampFromDatetimeLocal(endTime).toNumber());
|
||||
if (timeoutDate <= new Date()) {
|
||||
setEndTimeError("End time must be a date in the future");
|
||||
return false;
|
||||
}
|
||||
const timeoutDate = new Date(timestampFromDatetimeLocal(endTime).toNumber());
|
||||
if (timeoutDate <= new Date()) {
|
||||
setEndTimeError("End time must be a date in the future");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
const amountInAtomics = amount
|
||||
? Decimal.fromUserInput(amount, Number(chain.displayDenomExponent)).atomics
|
||||
: "0";
|
||||
const microCoin = (() => {
|
||||
try {
|
||||
return macroCoinToMicroCoin({ denom: chain.displayDenom, amount }, chain.assets);
|
||||
} catch {
|
||||
return { denom: chain.displayDenom, amount: "0" };
|
||||
}
|
||||
})();
|
||||
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.CreateVestingAccount].fromPartial({
|
||||
fromAddress,
|
||||
toAddress,
|
||||
amount: [{ amount: amountInAtomics, denom: chain.denom }],
|
||||
endTime: timestampFromDatetimeLocal(endTime, "s"),
|
||||
delayed,
|
||||
});
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.CreateVestingAccount].fromPartial({
|
||||
fromAddress,
|
||||
toAddress,
|
||||
amount: [microCoin],
|
||||
endTime: timestampFromDatetimeLocal(endTime, "s"),
|
||||
delayed,
|
||||
});
|
||||
|
||||
const msg: EncodeObject = { typeUrl: MsgTypeUrls.CreateVestingAccount, value: msgValue };
|
||||
const msg: EncodeObject = { typeUrl: MsgTypeUrls.CreateVestingAccount, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
} catch {}
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
chain.denom,
|
||||
chain.displayDenomExponent,
|
||||
chain.displayDenom,
|
||||
delayed,
|
||||
endTime,
|
||||
fromAddress,
|
||||
setMsgGetter,
|
||||
toAddress,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -103,7 +108,10 @@ const MsgCreateVestingAccountForm = ({
|
||||
label="Recipient Address"
|
||||
name="recipient-address"
|
||||
value={toAddress}
|
||||
onChange={({ target }) => setToAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setToAddress(target.value);
|
||||
setToAddressError("");
|
||||
}}
|
||||
error={toAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -114,7 +122,10 @@ const MsgCreateVestingAccountForm = ({
|
||||
label={`Amount (${chain.displayDenom})`}
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
@ -124,7 +135,10 @@ const MsgCreateVestingAccountForm = ({
|
||||
label="End time"
|
||||
name="end-time"
|
||||
value={endTime}
|
||||
onChange={({ target }) => setEndTime(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setEndTime(target.value);
|
||||
setEndTimeError("");
|
||||
}}
|
||||
error={endTimeError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
import { MsgDelegateEncodeObject } from "@cosmjs/stargate";
|
||||
import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -23,52 +23,57 @@ const MsgDelegateForm = ({ delegatorAddress, setMsgGetter, deleteMsg }: MsgDeleg
|
||||
const [validatorAddressError, setValidatorAddressError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ validatorAddress, amount });
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { validatorAddress, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setValidatorAddressError("");
|
||||
setAmountError("");
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
const addressErrorMsg = checkAddress(validatorAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setValidatorAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const addressErrorMsg = checkAddress(validatorAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setValidatorAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
const amountInAtomics = Decimal.fromUserInput(
|
||||
amount || "0",
|
||||
Number(chain.displayDenomExponent),
|
||||
).atomics;
|
||||
const microCoin = (() => {
|
||||
try {
|
||||
return macroCoinToMicroCoin({ denom: chain.displayDenom, amount }, chain.assets);
|
||||
} catch {
|
||||
return { denom: chain.displayDenom, amount: "0" };
|
||||
}
|
||||
})();
|
||||
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.Delegate].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorAddress,
|
||||
amount: { amount: amountInAtomics, denom: chain.denom },
|
||||
});
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.Delegate].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorAddress,
|
||||
amount: microCoin,
|
||||
});
|
||||
|
||||
const msg: MsgDelegateEncodeObject = { typeUrl: MsgTypeUrls.Delegate, value: msgValue };
|
||||
const msg: MsgDelegateEncodeObject = { typeUrl: MsgTypeUrls.Delegate, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
} catch {}
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
chain.denom,
|
||||
chain.displayDenomExponent,
|
||||
chain.displayDenom,
|
||||
delegatorAddress,
|
||||
setMsgGetter,
|
||||
validatorAddress,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -82,7 +87,10 @@ const MsgDelegateForm = ({ delegatorAddress, setMsgGetter, deleteMsg }: MsgDeleg
|
||||
label="Validator Address"
|
||||
name="validator-address"
|
||||
value={validatorAddress}
|
||||
onChange={({ target }) => setValidatorAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setValidatorAddress(target.value);
|
||||
setValidatorAddressError("");
|
||||
}}
|
||||
error={validatorAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -93,7 +101,10 @@ const MsgDelegateForm = ({ delegatorAddress, setMsgGetter, deleteMsg }: MsgDeleg
|
||||
label={`Amount (${chain.displayDenom})`}
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,7 @@ import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { ChainInfo } from "../../../../context/ChainsContext/types";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import Select from "../../../inputs/Select";
|
||||
@ -50,12 +50,17 @@ const MsgExecuteContractForm = ({
|
||||
const [customDenomError, setCustomDenomError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ contractAddress, customDenom, amount });
|
||||
|
||||
useEffect(() => {
|
||||
setContractAddressError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { contractAddress, customDenom, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setContractAddressError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
|
||||
if (jsonError.current) {
|
||||
return false;
|
||||
}
|
||||
@ -115,16 +120,14 @@ const MsgExecuteContractForm = ({
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
contractAddress,
|
||||
customDenom,
|
||||
fromAddress,
|
||||
msgContent,
|
||||
selectedDenom.value,
|
||||
setMsgGetter,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -138,7 +141,10 @@ const MsgExecuteContractForm = ({
|
||||
label="Contract Address"
|
||||
name="contract-address"
|
||||
value={contractAddress}
|
||||
onChange={({ target }) => setContractAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setContractAddress(target.value);
|
||||
setContractAddressError("");
|
||||
}}
|
||||
error={contractAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -165,6 +171,7 @@ const MsgExecuteContractForm = ({
|
||||
if (option.value !== customDenomOption.value) {
|
||||
setCustomDenom("");
|
||||
}
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -174,7 +181,10 @@ const MsgExecuteContractForm = ({
|
||||
label="Custom denom"
|
||||
name="custom-denom"
|
||||
value={customDenom}
|
||||
onChange={({ target }) => setCustomDenom(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCustomDenom(target.value);
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
placeholder={
|
||||
selectedDenom.value === customDenomOption.value
|
||||
? "Enter custom denom"
|
||||
@ -191,7 +201,10 @@ const MsgExecuteContractForm = ({
|
||||
label="Amount"
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,7 @@ import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { ChainInfo } from "../../../../context/ChainsContext/types";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import Select from "../../../inputs/Select";
|
||||
@ -56,15 +56,20 @@ const MsgInstantiateContract2Form = ({
|
||||
const [customDenomError, setCustomDenomError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ codeId, label, adminAddress, salt, customDenom, amount });
|
||||
|
||||
useEffect(() => {
|
||||
setCodeIdError("");
|
||||
setLabelError("");
|
||||
setAdminAddressError("");
|
||||
setSaltError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { codeId, label, adminAddress, salt, customDenom, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setCodeIdError("");
|
||||
setLabelError("");
|
||||
setAdminAddressError("");
|
||||
setSaltError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
|
||||
if (jsonError.current) {
|
||||
return false;
|
||||
}
|
||||
@ -160,19 +165,14 @@ const MsgInstantiateContract2Form = ({
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
adminAddress,
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
codeId,
|
||||
customDenom,
|
||||
fromAddress,
|
||||
label,
|
||||
msgContent,
|
||||
salt,
|
||||
selectedDenom.value,
|
||||
setMsgGetter,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -186,7 +186,10 @@ const MsgInstantiateContract2Form = ({
|
||||
label="Code ID"
|
||||
name="code-id"
|
||||
value={codeId}
|
||||
onChange={({ target }) => setCodeId(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCodeId(target.value);
|
||||
setCodeIdError("");
|
||||
}}
|
||||
error={codeIdError}
|
||||
/>
|
||||
</div>
|
||||
@ -195,7 +198,10 @@ const MsgInstantiateContract2Form = ({
|
||||
label="Label"
|
||||
name="label"
|
||||
value={label}
|
||||
onChange={({ target }) => setLabel(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setLabel(target.value);
|
||||
setLabelError("");
|
||||
}}
|
||||
error={labelError}
|
||||
/>
|
||||
</div>
|
||||
@ -204,7 +210,10 @@ const MsgInstantiateContract2Form = ({
|
||||
label="Admin Address"
|
||||
name="admin-address"
|
||||
value={adminAddress}
|
||||
onChange={({ target }) => setAdminAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAdminAddress(target.value);
|
||||
setAdminAddressError("");
|
||||
}}
|
||||
error={adminAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -215,7 +224,10 @@ const MsgInstantiateContract2Form = ({
|
||||
name="salt"
|
||||
placeholder="E.g. 1bac68"
|
||||
value={salt}
|
||||
onChange={({ target }) => setSalt(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setSalt(target.value);
|
||||
setSaltError("");
|
||||
}}
|
||||
error={saltError}
|
||||
/>
|
||||
</div>
|
||||
@ -241,6 +253,7 @@ const MsgInstantiateContract2Form = ({
|
||||
if (option.value !== customDenomOption.value) {
|
||||
setCustomDenom("");
|
||||
}
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -250,7 +263,10 @@ const MsgInstantiateContract2Form = ({
|
||||
label="Custom denom"
|
||||
name="custom-denom"
|
||||
value={customDenom}
|
||||
onChange={({ target }) => setCustomDenom(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCustomDenom(target.value);
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
placeholder={
|
||||
selectedDenom.value === customDenomOption.value
|
||||
? "Enter custom denom"
|
||||
@ -267,7 +283,10 @@ const MsgInstantiateContract2Form = ({
|
||||
label="Amount"
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,7 @@ import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { ChainInfo } from "../../../../context/ChainsContext/types";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import Select from "../../../inputs/Select";
|
||||
@ -54,14 +54,19 @@ const MsgInstantiateContractForm = ({
|
||||
const [customDenomError, setCustomDenomError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ codeId, label, adminAddress, customDenom, amount });
|
||||
|
||||
useEffect(() => {
|
||||
setCodeIdError("");
|
||||
setLabelError("");
|
||||
setAdminAddressError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { codeId, label, adminAddress, customDenom, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setCodeIdError("");
|
||||
setLabelError("");
|
||||
setAdminAddressError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
|
||||
if (jsonError.current) {
|
||||
return false;
|
||||
}
|
||||
@ -136,18 +141,14 @@ const MsgInstantiateContractForm = ({
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
adminAddress,
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
codeId,
|
||||
customDenom,
|
||||
fromAddress,
|
||||
label,
|
||||
msgContent,
|
||||
selectedDenom.value,
|
||||
setMsgGetter,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -161,7 +162,10 @@ const MsgInstantiateContractForm = ({
|
||||
label="Code ID"
|
||||
name="code-id"
|
||||
value={codeId}
|
||||
onChange={({ target }) => setCodeId(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCodeId(target.value);
|
||||
setCodeIdError("");
|
||||
}}
|
||||
error={codeIdError}
|
||||
/>
|
||||
</div>
|
||||
@ -170,7 +174,10 @@ const MsgInstantiateContractForm = ({
|
||||
label="Label"
|
||||
name="label"
|
||||
value={label}
|
||||
onChange={({ target }) => setLabel(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setLabel(target.value);
|
||||
setLabelError("");
|
||||
}}
|
||||
error={labelError}
|
||||
/>
|
||||
</div>
|
||||
@ -179,7 +186,10 @@ const MsgInstantiateContractForm = ({
|
||||
label="Admin Address"
|
||||
name="admin-address"
|
||||
value={adminAddress}
|
||||
onChange={({ target }) => setAdminAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAdminAddress(target.value);
|
||||
setAdminAddressError("");
|
||||
}}
|
||||
error={adminAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -206,6 +216,7 @@ const MsgInstantiateContractForm = ({
|
||||
if (option.value !== customDenomOption.value) {
|
||||
setCustomDenom("");
|
||||
}
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -215,7 +226,10 @@ const MsgInstantiateContractForm = ({
|
||||
label="Custom denom"
|
||||
name="custom-denom"
|
||||
value={customDenom}
|
||||
onChange={({ target }) => setCustomDenom(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCustomDenom(target.value);
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
placeholder={
|
||||
selectedDenom.value === customDenomOption.value
|
||||
? "Enter custom denom"
|
||||
@ -232,7 +246,10 @@ const MsgInstantiateContractForm = ({
|
||||
label="Amount"
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,7 @@ import dynamic from "next/dynamic";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -32,11 +32,16 @@ const MsgMigrateContractForm = ({
|
||||
const [contractAddressError, setContractAddressError] = useState("");
|
||||
const [codeIdError, setCodeIdError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ contractAddress, codeId });
|
||||
|
||||
useEffect(() => {
|
||||
setCodeIdError("");
|
||||
setContractAddressError("");
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { contractAddress, codeId } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setContractAddressError("");
|
||||
setCodeIdError("");
|
||||
|
||||
if (jsonError.current) {
|
||||
return false;
|
||||
}
|
||||
@ -74,15 +79,7 @@ const MsgMigrateContractForm = ({
|
||||
const msg: MsgMigrateContractEncodeObject = { typeUrl: MsgTypeUrls.Migrate, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
chain.addressPrefix,
|
||||
chain.chainId,
|
||||
codeId,
|
||||
contractAddress,
|
||||
fromAddress,
|
||||
msgContent,
|
||||
setMsgGetter,
|
||||
]);
|
||||
}, [chain.addressPrefix, chain.chainId, fromAddress, msgContent, setMsgGetter, trimmedInputs]);
|
||||
|
||||
return (
|
||||
<StackableContainer lessPadding lessMargin>
|
||||
@ -95,7 +92,10 @@ const MsgMigrateContractForm = ({
|
||||
label="Contract Address"
|
||||
name="contract-address"
|
||||
value={contractAddress}
|
||||
onChange={({ target }) => setContractAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setContractAddress(target.value);
|
||||
setContractAddressError("");
|
||||
}}
|
||||
error={contractAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -105,7 +105,10 @@ const MsgMigrateContractForm = ({
|
||||
label="Code ID"
|
||||
name="code-id"
|
||||
value={codeId}
|
||||
onChange={({ target }) => setCodeId(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCodeId(target.value);
|
||||
setCodeIdError("");
|
||||
}}
|
||||
error={codeIdError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
import { EncodeObject } from "@cosmjs/proto-signing";
|
||||
import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -29,63 +29,67 @@ const MsgRedelegateForm = ({
|
||||
const [validatorDstAddressError, setValidatorDstAddressError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ validatorSrcAddress, validatorDstAddress, amount });
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { validatorSrcAddress, validatorDstAddress, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setValidatorSrcAddressError("");
|
||||
setValidatorDstAddressError("");
|
||||
setAmountError("");
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
const srcAddressErrorMsg = checkAddress(validatorSrcAddress, chain.addressPrefix);
|
||||
if (srcAddressErrorMsg) {
|
||||
setValidatorSrcAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${srcAddressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const srcAddressErrorMsg = checkAddress(validatorSrcAddress, chain.addressPrefix);
|
||||
if (srcAddressErrorMsg) {
|
||||
setValidatorSrcAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${srcAddressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const dstAddressErrorMsg = checkAddress(validatorDstAddress, chain.addressPrefix);
|
||||
if (dstAddressErrorMsg) {
|
||||
setValidatorDstAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${dstAddressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const dstAddressErrorMsg = checkAddress(validatorDstAddress, chain.addressPrefix);
|
||||
if (dstAddressErrorMsg) {
|
||||
setValidatorDstAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${dstAddressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
const amountInAtomics = Decimal.fromUserInput(
|
||||
amount || "0",
|
||||
Number(chain.displayDenomExponent),
|
||||
).atomics;
|
||||
const microCoin = (() => {
|
||||
try {
|
||||
return macroCoinToMicroCoin({ denom: chain.displayDenom, amount }, chain.assets);
|
||||
} catch {
|
||||
return { denom: chain.displayDenom, amount: "0" };
|
||||
}
|
||||
})();
|
||||
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.BeginRedelegate].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorSrcAddress,
|
||||
validatorDstAddress,
|
||||
amount: { amount: amountInAtomics, denom: chain.denom },
|
||||
});
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.BeginRedelegate].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorSrcAddress,
|
||||
validatorDstAddress,
|
||||
amount: microCoin,
|
||||
});
|
||||
|
||||
const msg: EncodeObject = { typeUrl: MsgTypeUrls.BeginRedelegate, value: msgValue };
|
||||
const msg: EncodeObject = { typeUrl: MsgTypeUrls.BeginRedelegate, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
} catch {}
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
chain.denom,
|
||||
chain.displayDenomExponent,
|
||||
chain.displayDenom,
|
||||
delegatorAddress,
|
||||
setMsgGetter,
|
||||
validatorDstAddress,
|
||||
validatorSrcAddress,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -99,7 +103,10 @@ const MsgRedelegateForm = ({
|
||||
label="Source Validator Address"
|
||||
name="src-validator-address"
|
||||
value={validatorSrcAddress}
|
||||
onChange={({ target }) => setValidatorSrcAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setValidatorSrcAddress(target.value);
|
||||
setValidatorSrcAddressError("");
|
||||
}}
|
||||
error={validatorSrcAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -109,7 +116,10 @@ const MsgRedelegateForm = ({
|
||||
label="Destination Validator Address"
|
||||
name="dst-validator-address"
|
||||
value={validatorDstAddress}
|
||||
onChange={({ target }) => setValidatorDstAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setValidatorDstAddress(target.value);
|
||||
setValidatorDstAddressError("");
|
||||
}}
|
||||
error={validatorDstAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -120,7 +130,10 @@ const MsgRedelegateForm = ({
|
||||
label={`Amount (${chain.displayDenom})`}
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { RegistryAsset } from "../../../../types/chainRegistry";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
@ -40,12 +40,17 @@ const MsgSendForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgSendFormProps)
|
||||
const [customDenomError, setCustomDenomError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ toAddress, customDenom, amount });
|
||||
|
||||
useEffect(() => {
|
||||
setToAddressError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { toAddress, customDenom, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setToAddressError("");
|
||||
setCustomDenomError("");
|
||||
setAmountError("");
|
||||
|
||||
const addressErrorMsg = checkAddress(toAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setToAddressError(`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`);
|
||||
@ -91,15 +96,13 @@ const MsgSendForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgSendFormProps)
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
customDenom,
|
||||
fromAddress,
|
||||
selectedDenom.value,
|
||||
setMsgGetter,
|
||||
toAddress,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -113,7 +116,10 @@ const MsgSendForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgSendFormProps)
|
||||
label="Recipient Address"
|
||||
name="recipient-address"
|
||||
value={toAddress}
|
||||
onChange={({ target }) => setToAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setToAddress(target.value);
|
||||
setToAddressError("");
|
||||
}}
|
||||
error={toAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -130,6 +136,7 @@ const MsgSendForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgSendFormProps)
|
||||
if (option.value !== customDenomOption.value) {
|
||||
setCustomDenom("");
|
||||
}
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -139,7 +146,10 @@ const MsgSendForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgSendFormProps)
|
||||
label="Custom denom"
|
||||
name="custom-denom"
|
||||
value={customDenom}
|
||||
onChange={({ target }) => setCustomDenom(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setCustomDenom(target.value);
|
||||
setCustomDenomError("");
|
||||
}}
|
||||
placeholder={
|
||||
selectedDenom.value === customDenomOption.value
|
||||
? "Enter custom denom"
|
||||
@ -156,7 +166,10 @@ const MsgSendForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgSendFormProps)
|
||||
label="Amount"
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -2,7 +2,7 @@ import { EncodeObject } from "@cosmjs/proto-signing";
|
||||
import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -23,31 +23,32 @@ const MsgSetWithdrawAddressForm = ({
|
||||
const [withdrawAddress, setWithdrawAddress] = useState("");
|
||||
const [withdrawAddressError, setWithdrawAddressError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ withdrawAddress });
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { withdrawAddress } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setWithdrawAddressError("");
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
const addressErrorMsg = checkAddress(withdrawAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setWithdrawAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const addressErrorMsg = checkAddress(withdrawAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setWithdrawAddressError(`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.SetWithdrawAddress].fromPartial({
|
||||
delegatorAddress,
|
||||
withdrawAddress,
|
||||
});
|
||||
const msg: EncodeObject = { typeUrl: MsgTypeUrls.SetWithdrawAddress, value: msgValue };
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.SetWithdrawAddress].fromPartial({
|
||||
delegatorAddress,
|
||||
withdrawAddress,
|
||||
});
|
||||
const msg: EncodeObject = { typeUrl: MsgTypeUrls.SetWithdrawAddress, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
} catch {}
|
||||
}, [chain.addressPrefix, chain.chainId, delegatorAddress, setMsgGetter, withdrawAddress]);
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [chain.addressPrefix, chain.chainId, delegatorAddress, setMsgGetter, trimmedInputs]);
|
||||
|
||||
return (
|
||||
<StackableContainer lessPadding lessMargin>
|
||||
@ -60,7 +61,10 @@ const MsgSetWithdrawAddressForm = ({
|
||||
label="Withdraw Address"
|
||||
name="withdraw-address"
|
||||
value={withdrawAddress}
|
||||
onChange={({ target }) => setWithdrawAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setWithdrawAddress(target.value);
|
||||
setWithdrawAddressError("");
|
||||
}}
|
||||
error={withdrawAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
datetimeLocalFromTimestamp,
|
||||
timestampFromDatetimeLocal,
|
||||
} from "../../../../lib/dateHelpers";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -32,39 +32,48 @@ interface MsgTransferFormProps {
|
||||
const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFormProps) => {
|
||||
const { chain } = useChains();
|
||||
|
||||
const [sourcePort, setSourcePort] = useState("transfer");
|
||||
const [sourceChannel, setSourceChannel] = useState("");
|
||||
const [toAddress, setToAddress] = useState("");
|
||||
const [denom, setDenom] = useState("");
|
||||
const [amount, setAmount] = useState("0");
|
||||
const [toAddress, setToAddress] = useState("");
|
||||
const [sourcePort, setSourcePort] = useState("transfer");
|
||||
const [sourceChannel, setSourceChannel] = useState("");
|
||||
const [timeout, setTimeout] = useState(
|
||||
datetimeLocalFromTimestamp(Date.now() + humanTimestampOptions[0].value),
|
||||
);
|
||||
const [memo, setMemo] = useState("");
|
||||
|
||||
const [sourcePortError, setSourcePortError] = useState("");
|
||||
const [sourceChannelError, setSourceChannelError] = useState("");
|
||||
const [toAddressError, setToAddressError] = useState("");
|
||||
const [denomError, setDenomError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
const [toAddressError, setToAddressError] = useState("");
|
||||
const [sourcePortError, setSourcePortError] = useState("");
|
||||
const [sourceChannelError, setSourceChannelError] = useState("");
|
||||
const [timeoutError, setTimeoutError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({
|
||||
toAddress,
|
||||
denom,
|
||||
amount,
|
||||
sourcePort,
|
||||
sourceChannel,
|
||||
timeout,
|
||||
memo,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setSourcePortError("");
|
||||
setSourceChannelError("");
|
||||
setDenomError("");
|
||||
setAmountError("");
|
||||
setToAddressError("");
|
||||
setTimeoutError("");
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { toAddress, denom, amount, sourcePort, sourceChannel, timeout, memo } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
if (!sourcePort) {
|
||||
setSourcePortError("Source port is required");
|
||||
return false;
|
||||
}
|
||||
setToAddressError("");
|
||||
setDenomError("");
|
||||
setAmountError("");
|
||||
setSourcePortError("");
|
||||
setSourceChannelError("");
|
||||
setTimeoutError("");
|
||||
|
||||
if (!sourceChannel) {
|
||||
setSourceChannelError("Source channel is required");
|
||||
const addressErrorMsg = checkAddress(toAddress, null); // Allow address from any chain
|
||||
if (addressErrorMsg) {
|
||||
setToAddressError(`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -78,9 +87,13 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
return false;
|
||||
}
|
||||
|
||||
const addressErrorMsg = checkAddress(toAddress, null); // Allow address from any chain
|
||||
if (addressErrorMsg) {
|
||||
setToAddressError(`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`);
|
||||
if (!sourcePort) {
|
||||
setSourcePortError("Source port is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sourceChannel) {
|
||||
setSourceChannelError("Source channel is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -106,18 +119,7 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
const msg: MsgTransferEncodeObject = { typeUrl: MsgTypeUrls.Transfer, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.chainId,
|
||||
denom,
|
||||
fromAddress,
|
||||
memo,
|
||||
setMsgGetter,
|
||||
sourceChannel,
|
||||
sourcePort,
|
||||
timeout,
|
||||
toAddress,
|
||||
]);
|
||||
}, [chain.chainId, fromAddress, setMsgGetter, trimmedInputs]);
|
||||
|
||||
return (
|
||||
<StackableContainer lessPadding lessMargin>
|
||||
@ -130,7 +132,10 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
label="Recipient Address"
|
||||
name="recipient-address"
|
||||
value={toAddress}
|
||||
onChange={({ target }) => setToAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setToAddress(target.value);
|
||||
setToAddressError("");
|
||||
}}
|
||||
error={toAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -140,7 +145,10 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
label="Denom"
|
||||
name="denom"
|
||||
value={denom}
|
||||
onChange={({ target }) => setDenom(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setDenom(target.value);
|
||||
setDenomError("");
|
||||
}}
|
||||
error={denomError}
|
||||
/>
|
||||
</div>
|
||||
@ -150,7 +158,10 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
label="Amount"
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
@ -159,7 +170,10 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
label="Source Port"
|
||||
name="source-port"
|
||||
value={sourcePort}
|
||||
onChange={({ target }) => setSourcePort(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setSourcePort(target.value);
|
||||
setSourcePortError("");
|
||||
}}
|
||||
error={sourcePortError}
|
||||
/>
|
||||
</div>
|
||||
@ -168,7 +182,10 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
label="Source Channel"
|
||||
name="source-channel"
|
||||
value={sourceChannel}
|
||||
onChange={({ target }) => setSourceChannel(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setSourceChannel(target.value);
|
||||
setSourceChannelError("");
|
||||
}}
|
||||
error={sourceChannelError}
|
||||
/>
|
||||
</div>
|
||||
@ -179,7 +196,10 @@ const MsgTransferForm = ({ fromAddress, setMsgGetter, deleteMsg }: MsgTransferFo
|
||||
label="Timeout"
|
||||
name="timeout"
|
||||
value={timeout}
|
||||
onChange={({ target }) => setTimeout(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setTimeout(target.value);
|
||||
setTimeoutError("");
|
||||
}}
|
||||
error={timeoutError}
|
||||
/>
|
||||
<datalist id="timestamp-options">
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
import { MsgUndelegateEncodeObject } from "@cosmjs/stargate";
|
||||
import { useEffect, useState } from "react";
|
||||
import { MsgGetter } from "..";
|
||||
import { useChains } from "../../../../context/ChainsContext";
|
||||
import { checkAddress, exampleAddress } from "../../../../lib/displayHelpers";
|
||||
import { macroCoinToMicroCoin } from "../../../../lib/coinHelpers";
|
||||
import { checkAddress, exampleAddress, trimStringsObj } from "../../../../lib/displayHelpers";
|
||||
import { MsgCodecs, MsgTypeUrls } from "../../../../types/txMsg";
|
||||
import Input from "../../../inputs/Input";
|
||||
import StackableContainer from "../../../layout/StackableContainer";
|
||||
@ -27,52 +27,57 @@ const MsgUndelegateForm = ({
|
||||
const [validatorAddressError, setValidatorAddressError] = useState("");
|
||||
const [amountError, setAmountError] = useState("");
|
||||
|
||||
const trimmedInputs = trimStringsObj({ validatorAddress, amount });
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { validatorAddress, amount } = trimmedInputs;
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
setValidatorAddressError("");
|
||||
setAmountError("");
|
||||
|
||||
const isMsgValid = (): boolean => {
|
||||
const addressErrorMsg = checkAddress(validatorAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setValidatorAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const addressErrorMsg = checkAddress(validatorAddress, chain.addressPrefix);
|
||||
if (addressErrorMsg) {
|
||||
setValidatorAddressError(
|
||||
`Invalid address for network ${chain.chainId}: ${addressErrorMsg}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
setAmountError("Amount must be greater than 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
const amountInAtomics = Decimal.fromUserInput(
|
||||
amount || "0",
|
||||
Number(chain.displayDenomExponent),
|
||||
).atomics;
|
||||
const microCoin = (() => {
|
||||
try {
|
||||
return macroCoinToMicroCoin({ denom: chain.displayDenom, amount }, chain.assets);
|
||||
} catch {
|
||||
return { denom: chain.displayDenom, amount: "0" };
|
||||
}
|
||||
})();
|
||||
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.Undelegate].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorAddress,
|
||||
amount: { amount: amountInAtomics, denom: chain.denom },
|
||||
});
|
||||
const msgValue = MsgCodecs[MsgTypeUrls.Undelegate].fromPartial({
|
||||
delegatorAddress,
|
||||
validatorAddress,
|
||||
amount: microCoin,
|
||||
});
|
||||
|
||||
const msg: MsgUndelegateEncodeObject = { typeUrl: MsgTypeUrls.Undelegate, value: msgValue };
|
||||
const msg: MsgUndelegateEncodeObject = { typeUrl: MsgTypeUrls.Undelegate, value: msgValue };
|
||||
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
} catch {}
|
||||
setMsgGetter({ isMsgValid, msg });
|
||||
}, [
|
||||
amount,
|
||||
chain.addressPrefix,
|
||||
chain.assets,
|
||||
chain.chainId,
|
||||
chain.denom,
|
||||
chain.displayDenomExponent,
|
||||
chain.displayDenom,
|
||||
delegatorAddress,
|
||||
setMsgGetter,
|
||||
validatorAddress,
|
||||
trimmedInputs,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -86,7 +91,10 @@ const MsgUndelegateForm = ({
|
||||
label="Validator Address"
|
||||
name="validator-address"
|
||||
value={validatorAddress}
|
||||
onChange={({ target }) => setValidatorAddress(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setValidatorAddress(target.value);
|
||||
setValidatorAddressError("");
|
||||
}}
|
||||
error={validatorAddressError}
|
||||
placeholder={`E.g. ${exampleAddress(0, chain.addressPrefix)}`}
|
||||
/>
|
||||
@ -97,7 +105,10 @@ const MsgUndelegateForm = ({
|
||||
label={`Amount (${chain.displayDenom})`}
|
||||
name="amount"
|
||||
value={amount}
|
||||
onChange={({ target }) => setAmount(target.value)}
|
||||
onChange={({ target }) => {
|
||||
setAmount(target.value);
|
||||
setAmountError("");
|
||||
}}
|
||||
error={amountError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user