Skip to content

Commit

Permalink
Merge pull request #29 from burnt-labs/dev/adjust-max-delegation
Browse files Browse the repository at this point in the history
Dev/adjust max delegation
  • Loading branch information
burnt-sun authored Dec 11, 2024
2 parents 727fd62 + eaee0ec commit f794d4e
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 38 deletions.
7 changes: 7 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,11 @@ export const REST_ENDPOINTS = {
balances: "/cosmos/bank/v1beta1/balances",
distributionParams: "/cosmos/distribution/v1beta1/params",
inflation: "/xion/mint/v1/inflation",
simulate: "/cosmos/tx/v1beta1/simulate",
} as const;

export const GAS_CONFIG = {
defaultMultiplier: 2.3,
defaultStakeEstimate: 200000,
price: "0.001",
} as const;
70 changes: 61 additions & 9 deletions src/features/staking/components/modals/redelegate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ import { useValidatorLogo } from "@/features/staking/hooks";
import { redelegateAction } from "../../context/actions";
import { useStaking } from "../../context/hooks";
import { setModalOpened } from "../../context/reducer";
import { getTotalDelegation } from "../../context/selectors";
import {
getTokensAvailableBG,
getTotalDelegation,
} from "../../context/selectors";
import { getXionCoin } from "../../lib/core/coins";
import { estimateGas } from "../../lib/core/gas";
import {
formatCoin,
formatToSmallDisplay,
Expand Down Expand Up @@ -164,10 +168,11 @@ const RedelegateModal = () => {
validator.operatorAddress,
);

const validateAmount = () => {
const validateAmount = async () => {
if (
!amountUSD ||
!delegatedTokens ||
!amountXIONParsed ||
amountXIONParsed.isNaN() ||
amountXIONParsed.lte(0) ||
amountXIONParsed.gt(new BigNumber(delegatedTokens.amount))
) {
Expand All @@ -178,17 +183,60 @@ const RedelegateModal = () => {

return true;
}

if (!dstValidator) {
setFormError({
...formError,
amount: "Please select a destination validator",
});

return true;
}

try {
const gasEstimate = await estimateGas({
amount: getXionCoin(amountXIONParsed),
delegator: account.bech32Address,
messageType: "redelegate",
redelegateParams: {
validatorDst: dstValidator.operatorAddress,
validatorSrc: validator.operatorAddress,
},
validator: validator.operatorAddress,
});

const availableTokens = getTokensAvailableBG(staking.state);

if (!availableTokens || gasEstimate.gt(availableTokens)) {
setFormError({
...formError,
amount: `Insufficient funds for fees. Need ~${gasEstimate.toString()} XION`,
});

return true;
}
} catch (error) {
setFormError({
...formError,
amount: "Failed to estimate transaction fees",
});

return true;
}

return false;
};

const onSubmit: FormEventHandler<HTMLFormElement> = (e) => {
e?.stopPropagation();
const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
e?.preventDefault();

if (validateAmount()) return;
if (!client) return;

if (!client || !amountXIONParsed.gt(0)) return;
const hasValidationError = await validateAmount();

setStep("review");
if (!hasValidationError) {
setStep("review");
}
};

return (
Expand Down Expand Up @@ -258,7 +306,7 @@ const RedelegateModal = () => {
</div>
<ModalDescription>
You are about to redelegate your token from{" "}
{validator.description.moniker} to
{validator.description.moniker} to{" "}
{dstValidator?.description.moniker}. Remember, you will not
able to redelegate these token within {UNBONDING_DAYS} days.
</ModalDescription>
Expand Down Expand Up @@ -322,6 +370,10 @@ const RedelegateModal = () => {
onChange={(_, validatorAddress) => {
if (!!validatorAddress) {
setDstValidator(validatorsPerAddress[validatorAddress]);

if (formError.amount) {
setFormError({ ...formError, amount: undefined });
}
}
}}
renderValue={(option: null | SelectOption<string>) =>
Expand Down
96 changes: 67 additions & 29 deletions src/features/staking/components/modals/staking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { useStaking } from "../../context/hooks";
import { setModalOpened } from "../../context/reducer";
import { getTokensAvailableBG } from "../../context/selectors";
import { getXionCoin } from "../../lib/core/coins";
import { estimateGas } from "../../lib/core/gas";
import type { StakeAddresses } from "../../lib/core/tx";
import { formatCoin, formatXionToUSD } from "../../lib/formatters";

Expand Down Expand Up @@ -50,6 +51,7 @@ const StakingModal = () => {
const { account, staking } = stakingRef;
const { modal } = staking.state;
const isOpen = modal?.type === "delegate";
const validator = isOpen ? modal?.content?.validator : undefined;

useEffect(
() => () => {
Expand All @@ -63,8 +65,6 @@ const StakingModal = () => {

if (!isOpen) return null;

const { validator } = modal?.content;

if (!validator) return null;

const amountXIONParsed = new BigNumber(amountXION);
Expand All @@ -79,6 +79,71 @@ const StakingModal = () => {

const availableTokens = getTokensAvailableBG(staking.state);

const validateAmount = async () => {
if (!availableTokens) {
setFormError({
...formError,
amount: "No tokens available",
});

return true;
}

if (
!amountXIONParsed ||
amountXIONParsed.isNaN() ||
amountXIONParsed.lte(0)
) {
setFormError({
...formError,
amount: "Invalid amount",
});

return true;
}

try {
const gasEstimate = await estimateGas({
amount: getXionCoin(amountXIONParsed),
delegator: account.bech32Address,
messageType: "delegate",
validator: validator.operatorAddress,
});

const totalRequired = amountXIONParsed.plus(gasEstimate);

if (totalRequired.gt(availableTokens)) {
setFormError({
...formError,
amount: `Amount too high. Need ~${gasEstimate.toString()} XION for fees`,
});

return true;
}
} catch (error) {
setFormError({
...formError,
amount: "Failed to estimate transaction fees",
});

return true;
}

return false;
};

const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
e?.preventDefault();

if (!client) return;

const hasValidationError = await validateAmount();

if (!hasValidationError) {
setStep("review");
}
};

return (
<CommonModal
isOpen={isOpen}
Expand Down Expand Up @@ -184,33 +249,6 @@ const StakingModal = () => {
);
}

const validateAmount = () => {
if (
!amountUSD ||
!availableTokens ||
amountXIONParsed.isNaN() ||
amountXIONParsed.gt(availableTokens)
) {
setFormError({
...formError,
amount: "Invalid amount",
});

return true;
}
};

const onSubmit: FormEventHandler<HTMLFormElement> = (e) => {
e?.stopPropagation();
e?.preventDefault();

if (validateAmount()) return;

if (!client || hasErrors || amountXIONParsed.lt(0)) return;

setStep("review");
};

return (
<>
<div className="mb-[35px] text-center uppercase">
Expand Down
Loading

0 comments on commit f794d4e

Please sign in to comment.