Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update unbonding period calculation #1034

Merged
merged 7 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/extension/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"],
"typeRoots": ["./node_modules/@types"],
"typeRoots": ["./node_modules/@types"]
}
8 changes: 5 additions & 3 deletions apps/namadillo/src/App/Staking/IncrementBonding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { NamCurrency } from "App/Common/NamCurrency";
import { TableRowLoading } from "App/Common/TableRowLoading";
import { TransactionFees } from "App/Common/TransactionFees";
import { accountBalanceAtom, defaultAccountAtom } from "atoms/accounts";
import { chainParametersAtom } from "atoms/chain";
import { gasLimitsAtom, minimumGasPriceAtom } from "atoms/fees";
import {
createNotificationId,
Expand All @@ -33,6 +34,7 @@ const IncrementBonding = (): JSX.Element => {
const [filter, setFilter] = useState<string>("");
const [onlyMyValidators, setOnlyMyValidators] = useState(false);
const navigate = useNavigate();
const { data: chainParameters } = useAtomValue(chainParametersAtom);
const accountBalance = useAtomValue(accountBalanceAtom);
const gasPrice = useAtomValue(minimumGasPriceAtom);
const gasLimits = useAtomValue(gasLimitsAtom);
Expand Down Expand Up @@ -201,9 +203,9 @@ const IncrementBonding = (): JSX.Element => {
<GoAlert />
</i>
<p className="text-balance">
Staking will lock and bind your assets to the TODO
unbonding schedule. To make your NAM liquid again, you
will need to unstake.
Staking will lock and bind your assets to a{" "}
{chainParameters?.unbondingPeriod} unbonding schedule.
To make your NAM liquid again, you will need to unstake.
</p>
</div>
</Alert>
Expand Down
14 changes: 2 additions & 12 deletions apps/namadillo/src/App/Staking/Unstake.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ActionButton, Alert, Modal, Panel, Stack } from "@namada/components";
import { UnbondMsgValue, UnbondProps } from "@namada/types";
import { singleUnitDurationFromInterval } from "@namada/utils/helpers";
import { AtomErrorBoundary } from "App/Common/AtomErrorBoundary";
import { Info } from "App/Common/Info";
import { ModalContainer } from "App/Common/ModalContainer";
Expand All @@ -24,19 +23,11 @@ import { useAtomValue, useSetAtom } from "jotai";
import { TransactionPair, broadcastTx } from "lib/query";
import { FormEvent, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { EpochInfo, MyValidator } from "types";
import { MyValidator } from "types";
import { BondingAmountOverview } from "./BondingAmountOverview";
import { UnstakeBondingTable } from "./UnstakeBondingTable";
import StakingRoutes from "./routes";

const getUnbondPeriod = ({
unbondingPeriodInEpochs,
minEpochDuration,
}: EpochInfo): string => {
const duration = unbondingPeriodInEpochs * minEpochDuration;
return singleUnitDurationFromInterval(0, duration);
};

const Unstake = (): JSX.Element => {
const navigate = useNavigate();
const { data: account } = useAtomValue(defaultAccountAtom);
Expand Down Expand Up @@ -158,8 +149,7 @@ const Unstake = (): JSX.Element => {
return "";
})();

const unbondPeriod =
chainParameters ? getUnbondPeriod(chainParameters.epochInfo) : "N/A";
const unbondPeriod = chainParameters?.unbondingPeriod;

return (
<Modal onClose={onCloseModal}>
Expand Down
14 changes: 11 additions & 3 deletions apps/namadillo/src/atoms/chain/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {
rpcUrlAtom,
} from "atoms/settings";
import { queryDependentFn } from "atoms/utils";
import BigNumber from "bignumber.js";
import { atomWithQuery } from "jotai-tanstack-query";
import { ChainParameters, ChainSettings } from "types";
import { calculateUnbondingPeriod } from "./functions";
import { fetchChainParameters, fetchRpcUrlFromIndexer } from "./services";

export const chainAtom = atomWithQuery<ChainSettings>((get) => {
Expand All @@ -30,8 +32,7 @@ export const chainAtom = atomWithQuery<ChainSettings>((get) => {
bench32Prefix: namada.bech32Prefix,
rpcUrl,
chainId: chainParameters.data!.chainId,
unbondingPeriodInEpochs:
chainParameters.data!.epochInfo.unbondingPeriodInEpochs,
unbondingPeriod: chainParameters.data!.unbondingPeriod,
nativeTokenAddress: chainParameters.data!.nativeTokenAddress,
checksums: chainParameters.data!.checksums,
};
Expand Down Expand Up @@ -70,6 +71,13 @@ export const chainParametersAtom = atomWithQuery<ChainParameters>((get) => {
queryKey: ["chain-parameters", indexerUrl],
staleTime: Infinity,
enabled: !!indexerUrl,
queryFn: async () => fetchChainParameters(api),
queryFn: async () => {
const parameters = await fetchChainParameters(api);
return {
...parameters,
apr: BigNumber(parameters.apr),
unbondingPeriod: calculateUnbondingPeriod(parameters),
};
},
};
});
23 changes: 23 additions & 0 deletions apps/namadillo/src/atoms/chain/functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Parameters } from "@anomaorg/namada-indexer-client";
import { singleUnitDurationFromInterval } from "@namada/utils/helpers";

export const calculateUnbondingPeriod = (parameters: Parameters): string => {
const unbondingPeriodInEpochs =
Number(parameters.unbondingLength) +
Number(parameters.pipelineLength) +
// + 1 because we unbonding period starts from the next epoch
1;
const minEpochDuration = Number(parameters.minDuration);
const minNumOfBlocks = Number(parameters.minNumOfBlocks);
const epochSwitchBlocksDelay = Number(parameters.epochSwitchBlocksDelay);

// Because epoch duration is in reality longer by epochSwitchBlocksDelay we have to account for that
const timePerBlock = minEpochDuration / minNumOfBlocks;
const realMinEpochDuration =
minEpochDuration + timePerBlock * epochSwitchBlocksDelay;

return singleUnitDurationFromInterval(
0,
unbondingPeriodInEpochs * realMinEpochDuration
);
};
24 changes: 3 additions & 21 deletions apps/namadillo/src/atoms/chain/services.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { DefaultApi } from "@anomaorg/namada-indexer-client";
import BigNumber from "bignumber.js";
import { ChainParameters } from "types";
import { DefaultApi, Parameters } from "@anomaorg/namada-indexer-client";

export const fetchRpcUrlFromIndexer = async (
api: DefaultApi
Expand All @@ -11,23 +9,7 @@ export const fetchRpcUrlFromIndexer = async (

export const fetchChainParameters = async (
api: DefaultApi
): Promise<ChainParameters> => {
): Promise<Parameters> => {
const parametersResponse = await api.apiV1ChainParametersGet();
const parameters = parametersResponse.data;
return {
epochInfo: {
unbondingPeriodInEpochs:
Number(parameters.unbondingLength) +
Number(parameters.pipelineLength) +
// + 1 because we unbonding period starts from the next epoch
1,
minEpochDuration: Number(parameters.minDuration),
minNumOfBlocks: Number(parameters.minNumOfBlocks),
epochSwitchBlocksDelay: Number(parameters.epochSwitchBlocksDelay),
},
apr: BigNumber(parameters.apr),
chainId: parameters.chainId,
nativeTokenAddress: parameters.nativeTokenAddress,
checksums: parameters.checksums,
};
return parametersResponse.data;
};
23 changes: 6 additions & 17 deletions apps/namadillo/src/atoms/validators/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,17 @@ import {
} from "@anomaorg/namada-indexer-client";
import { singleUnitDurationFromInterval } from "@namada/utils";
import BigNumber from "bignumber.js";
import { EpochInfo, MyUnbondingValidator, MyValidator, Validator } from "types";
import { MyUnbondingValidator, MyValidator, Validator } from "types";

export const toValidator = (
indexerValidator: IndexerValidator,
indexerVotingPower: IndexerVotingPower,
epochInfo: EpochInfo,
unbondingPeriod: string,
nominalApr: BigNumber
): Validator => {
const commission = BigNumber(indexerValidator.commission);
const expectedApr = nominalApr.times(1 - commission.toNumber());

// Because epoch duration is in reality longer by epochSwitchBlocksDelay we have to account for that
const timePerBlock = epochInfo.minEpochDuration / epochInfo.minNumOfBlocks;
const realMinEpochDuration =
epochInfo.minEpochDuration +
timePerBlock * epochInfo.epochSwitchBlocksDelay;

const unbondingPeriod = singleUnitDurationFromInterval(
0,
epochInfo.unbondingPeriodInEpochs * realMinEpochDuration
);

return {
uuid: indexerValidator.address,
alias: indexerValidator.name,
Expand All @@ -48,14 +37,14 @@ export const toValidator = (
export const toMyValidators = (
indexerBonds: IndexerBond[],
totalVotingPower: IndexerVotingPower,
epochInfo: EpochInfo,
unbondingPeriod: string,
apr: BigNumber
): MyValidator[] => {
return indexerBonds.map((indexerBond) => {
const validator = toValidator(
indexerBond.validator,
totalVotingPower,
epochInfo,
unbondingPeriod,
apr
);

Expand All @@ -73,7 +62,7 @@ export const toMyValidators = (
export const toUnbondingValidators = (
indexerBonds: IndexerUnbond[],
totalVotingPower: IndexerVotingPower,
epochInfo: EpochInfo,
unbondingPeriod: string,
apr: BigNumber
): MyUnbondingValidator[] => {
const timeNow = Math.round(Date.now() / 1000);
Expand All @@ -82,7 +71,7 @@ export const toUnbondingValidators = (
const validator = toValidator(
indexerUnbond.validator,
totalVotingPower,
epochInfo,
unbondingPeriod,
apr
);
const withdrawTime = Number(indexerUnbond.withdrawTime);
Expand Down
9 changes: 3 additions & 6 deletions apps/namadillo/src/atoms/validators/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@ export const fetchAllValidators = async (
chainParameters: ChainParameters,
votingPower: IndexerVotingPower
): Promise<Validator[]> => {
const epochInfo = chainParameters.epochInfo;
const nominalApr = chainParameters.apr;
const validatorsResponse = await api.apiV1PosValidatorAllGet([
IndexerValidatorStatus.Consensus,
]);

const validators = validatorsResponse.data;
return validators.map((v) =>
toValidator(v, votingPower, epochInfo, nominalApr)
toValidator(v, votingPower, chainParameters.unbondingPeriod, nominalApr)
);
};

Expand All @@ -47,15 +46,14 @@ export const fetchMyValidators = async (
chainParameters: ChainParameters,
votingPower: IndexerVotingPower
): Promise<MyValidator[]> => {
const epochInfo = chainParameters.epochInfo;
const apr = chainParameters.apr;
const bondsResponse = await api.apiV1PosMergedBondsAddressGet(
account.address
);
return toMyValidators(
bondsResponse.data.results,
votingPower,
epochInfo,
chainParameters.unbondingPeriod,
apr
);
};
Expand All @@ -66,15 +64,14 @@ export const fetchMyUnbonds = async (
chainParameters: ChainParameters,
votingPower: IndexerVotingPower
): Promise<MyUnbondingValidator[]> => {
const epochInfo = chainParameters.epochInfo;
const apr = chainParameters.apr;
const unbondsResponse = await api.apiV1PosMergedUnbondsAddressGet(
account.address
);
return toUnbondingValidators(
unbondsResponse.data.results,
votingPower,
epochInfo,
chainParameters.unbondingPeriod,
apr
);
};
10 changes: 1 addition & 9 deletions apps/namadillo/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export type ChainSettings = {
nativeTokenAddress: Address;
rpcUrl: string;
chainId: string;
unbondingPeriodInEpochs: number;
extensionId: ExtensionKey;
checksums: Record<string, string>;
};
Expand All @@ -39,18 +38,11 @@ export type SettingsTomlOptions = {
rpc_url?: string;
};

export type EpochInfo = {
unbondingPeriodInEpochs: number;
minEpochDuration: number;
minNumOfBlocks: number;
epochSwitchBlocksDelay: number;
};

export type ChainParameters = {
apr: BigNumber;
chainId: string;
nativeTokenAddress: Address;
epochInfo: EpochInfo;
unbondingPeriod: string;
checksums: Record<string, string>;
};

Expand Down
Loading