Skip to content

Commit 4f090ea

Browse files
committed
fix: fix fees and redelegating to same validator (#1043)
- Add default gas config and use it to display correct transaction fees - Disallow redelegating when it would result in no transactions (e.g. redelegating to the same validator) - Refactor redelegate validation and display clearer error message in submit button Fixes #975.
1 parent 3cc8af7 commit 4f090ea

File tree

9 files changed

+204
-94
lines changed

9 files changed

+204
-94
lines changed
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
import clsx from "clsx";
2-
import { useGasEstimate } from "hooks/useGasEstimate";
2+
import { GasConfig } from "types";
33
import { NamCurrency } from "./NamCurrency";
44
import { TextLink } from "./TextLink";
5+
56
type TransactionFeesProps = {
6-
numberOfTransactions: number;
7+
gasConfig: GasConfig;
78
className?: string;
89
};
910

1011
export const TransactionFees = ({
11-
numberOfTransactions,
12+
gasConfig,
1213
className,
1314
}: TransactionFeesProps): JSX.Element => {
14-
const { calculateMinGasRequired } = useGasEstimate();
15-
const minimumGas = calculateMinGasRequired(numberOfTransactions);
15+
const fee = gasConfig.gasPrice.times(gasConfig.gasLimit);
1616

17-
if (!minimumGas || minimumGas.eq(0)) return <></>;
1817
return (
1918
<div className={clsx("text-white text-sm", className)}>
2019
<TextLink>Transaction fee:</TextLink>{" "}
21-
<NamCurrency className="font-medium" amount={minimumGas} />
20+
<NamCurrency className="font-medium" amount={fee} />
2221
</div>
2322
);
2423
};

apps/namadillo/src/App/Governance/SubmitVote.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
voteTypes,
1414
} from "@namada/types";
1515
import { TransactionFees } from "App/Common/TransactionFees";
16-
import { gasLimitsAtom, minimumGasPriceAtom } from "atoms/fees";
16+
import { defaultGasConfigFamily } from "atoms/fees";
1717
import {
1818
createNotificationId,
1919
dispatchToastNotificationAtom,
@@ -59,8 +59,8 @@ export const WithProposalId: React.FC<{ proposalId: bigint }> = ({
5959
error: voteTxError,
6060
} = useAtomValue(createVoteTxAtom);
6161
const dispatchNotification = useSetAtom(dispatchToastNotificationAtom);
62-
const minimumGasPrice = useAtomValue(minimumGasPriceAtom);
63-
const gasLimits = useAtomValue(gasLimitsAtom);
62+
63+
const gasConfig = useAtomValue(defaultGasConfigFamily(["VoteProposal"]));
6464

6565
useEffect(() => {
6666
if (isSuccess) {
@@ -108,15 +108,13 @@ export const WithProposalId: React.FC<{ proposalId: bigint }> = ({
108108
typeof selectedVoteType !== "undefined",
109109
"There is no selected vote type"
110110
);
111-
invariant(minimumGasPrice.isSuccess, "Gas price loading is still pending");
112-
invariant(gasLimits.isSuccess, "Gas limit loading is still pending");
111+
if (!gasConfig.isSuccess) {
112+
throw new Error("Gas config is still pending");
113+
}
113114
createVoteTx({
114115
proposalId,
115116
vote: selectedVoteType,
116-
gasConfig: {
117-
gasPrice: minimumGasPrice.data!,
118-
gasLimit: gasLimits.data!.VoteProposal.native,
119-
},
117+
gasConfig: gasConfig.data,
120118
});
121119
};
122120

@@ -182,10 +180,12 @@ export const WithProposalId: React.FC<{ proposalId: bigint }> = ({
182180
/>
183181
</Stack>
184182
<footer>
185-
<TransactionFees
186-
className="flex justify-between"
187-
numberOfTransactions={1}
188-
/>
183+
{gasConfig.isSuccess && (
184+
<TransactionFees
185+
className="flex justify-between"
186+
gasConfig={gasConfig.data}
187+
/>
188+
)}
189189
</footer>
190190
<ActionButton
191191
type="submit"

apps/namadillo/src/App/Staking/IncrementBonding.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { NamCurrency } from "App/Common/NamCurrency";
77
import { TableRowLoading } from "App/Common/TableRowLoading";
88
import { TransactionFees } from "App/Common/TransactionFees";
99
import { accountBalanceAtom, defaultAccountAtom } from "atoms/accounts";
10-
import { gasLimitsAtom, minimumGasPriceAtom } from "atoms/fees";
10+
import { defaultGasConfigFamily } from "atoms/fees";
1111
import {
1212
createNotificationId,
1313
dispatchToastNotificationAtom,
@@ -34,8 +34,7 @@ const IncrementBonding = (): JSX.Element => {
3434
const [onlyMyValidators, setOnlyMyValidators] = useState(false);
3535
const navigate = useNavigate();
3636
const accountBalance = useAtomValue(accountBalanceAtom);
37-
const gasPrice = useAtomValue(minimumGasPriceAtom);
38-
const gasLimits = useAtomValue(gasLimitsAtom);
37+
3938
const { data: account } = useAtomValue(defaultAccountAtom);
4039
const validators = useAtomValue(allValidatorsAtom);
4140
const dispatchNotification = useSetAtom(dispatchToastNotificationAtom);
@@ -62,6 +61,12 @@ const IncrementBonding = (): JSX.Element => {
6261
parseUpdatedAmounts,
6362
} = useStakeModule({ account });
6463

64+
const gasConfig = useAtomValue(
65+
defaultGasConfigFamily(
66+
Array(Object.keys(updatedAmountByAddress).length).fill("Bond")
67+
)
68+
);
69+
6570
const filteredValidators = useValidatorFilter({
6671
validators: validators.isSuccess ? validators.data : [],
6772
myValidatorsAddresses: Array.from(
@@ -89,16 +94,15 @@ const IncrementBonding = (): JSX.Element => {
8994
"Extension is not connected or you don't have an account"
9095
);
9196
const changes = parseUpdatedAmounts();
92-
invariant(gasPrice.data, "Gas price loading is still pending");
93-
invariant(gasLimits.isSuccess, "Gas limit loading is still pending");
94-
const bondGasLimit = gasLimits.data!.Bond.native;
97+
98+
if (!gasConfig.isSuccess) {
99+
throw new Error("Gas config is still pending");
100+
}
101+
95102
createBondTransaction({
96103
changes,
97104
account,
98-
gasConfig: {
99-
gasPrice: gasPrice.data!,
100-
gasLimit: bondGasLimit.multipliedBy(changes.length),
101-
},
105+
gasConfig: gasConfig.data,
102106
});
103107
};
104108

@@ -266,10 +270,12 @@ const IncrementBonding = (): JSX.Element => {
266270
>
267271
{isPerformingBond ? "Processing..." : errorMessage || "Stake"}
268272
</ActionButton>
269-
<TransactionFees
270-
className="justify-self-end px-4"
271-
numberOfTransactions={Object.keys(updatedAmountByAddress).length}
272-
/>
273+
{gasConfig.isSuccess && (
274+
<TransactionFees
275+
className="justify-self-end px-4"
276+
gasConfig={gasConfig.data}
277+
/>
278+
)}
273279
</div>
274280
</form>
275281
</ModalContainer>

apps/namadillo/src/App/Staking/ReDelegate.tsx

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { RedelegateMsgValue } from "@namada/types";
33
import { Info } from "App/Common/Info";
44
import { ModalContainer } from "App/Common/ModalContainer";
55
import { defaultAccountAtom } from "atoms/accounts";
6-
import { gasLimitsAtom } from "atoms/fees";
6+
import { defaultGasConfigFamily } from "atoms/fees";
77
import {
88
createNotificationId,
99
dispatchToastNotificationAtom,
@@ -12,7 +12,6 @@ import { createReDelegateTxAtom } from "atoms/staking";
1212
import { allValidatorsAtom } from "atoms/validators";
1313
import BigNumber from "bignumber.js";
1414
import clsx from "clsx";
15-
import { useGasEstimate } from "hooks/useGasEstimate";
1615
import { useStakeModule } from "hooks/useStakeModule";
1716
import invariant from "invariant";
1817
import { useAtomValue, useSetAtom } from "jotai";
@@ -33,8 +32,6 @@ export const ReDelegate = (): JSX.Element => {
3332
Record<string, BigNumber>
3433
>({});
3534

36-
const { gasPrice } = useGasEstimate();
37-
const gasLimits = useAtomValue(gasLimitsAtom);
3835
const navigate = useNavigate();
3936
const dispatchNotification = useSetAtom(dispatchToastNotificationAtom);
4037
const { data: account } = useAtomValue(defaultAccountAtom);
@@ -49,6 +46,15 @@ export const ReDelegate = (): JSX.Element => {
4946
myValidators,
5047
} = useStakeModule({ account });
5148

49+
const changes = getAmountDistribution(
50+
amountsRemovedByAddress,
51+
amountsToAssignByAddress
52+
);
53+
54+
const gasConfig = useAtomValue(
55+
defaultGasConfigFamily(Array(changes.length).fill("Redelegate"))
56+
);
57+
5258
const {
5359
mutate: createRedelegateTx,
5460
isPending: isCreatingTx,
@@ -127,19 +133,18 @@ export const ReDelegate = (): JSX.Element => {
127133

128134
const performRedelegate = (): void => {
129135
invariant(account, `Extension is connected but you don't have an account`);
130-
invariant(gasPrice, "Gas price loading is still pending");
131-
invariant(gasLimits.isSuccess, "Gas limit loading is still pending");
132-
const redelegateGasLimit = gasLimits.data!.Redelegation.native;
133-
const changes = getAmountDistribution(
134-
amountsRemovedByAddress,
135-
amountsToAssignByAddress
136-
);
136+
137+
if (changes.length === 0) {
138+
throw new Error("No redelegation changes to make");
139+
}
140+
141+
if (!gasConfig.isSuccess) {
142+
throw new Error("Gas config loading is still pending");
143+
}
144+
137145
createRedelegateTx({
138146
changes,
139-
gasConfig: {
140-
gasPrice: gasPrice,
141-
gasLimit: redelegateGasLimit.multipliedBy(changes.length),
142-
},
147+
gasConfig: gasConfig.data,
143148
account,
144149
});
145150
};
@@ -250,6 +255,8 @@ export const ReDelegate = (): JSX.Element => {
250255
totalAssignedAmounts={totalAssignedAmounts}
251256
onChangeAssignedAmount={onAssignAmount}
252257
isPerformingRedelegation={isCreatingTx}
258+
redelegateChanges={changes}
259+
gasConfig={gasConfig}
253260
/>
254261
)}
255262
</form>

0 commit comments

Comments
 (0)