Skip to content

Commit

Permalink
feat(wallet-dashboard): style selected stake (#3832)
Browse files Browse the repository at this point in the history
* feat(tooling-dashboard): style selected stake

* feat(tooling-dashboard): add data to stake details page

* feat(wallet-dashboard): remove extra memo.

* feat(staking): refactor StakeDialog. Add new Layout component.

* feat(tooling-core): add clsx dependency to package.json and update pnpm-lock.yaml

* feat(wallet-dashboard): manage view for dialog outside.

* feat(wallet-dashboard): join changes from PR 3854

* feat(wallet-dashboard): join enter amount screen from PR 3874

* feat(tooling-core): move validation schema

* feat(wallet-dashboard): integrate Formik

* feat(wallet-dashboard): enhance StakeDialog and EnterAmountView with FormValues integration

* feat(wallet-dashboard): update StakeDialog to support selectedValidator and optional setView

* feat(wallet-dashboard): refactor StakedInfo and Validator components to use core hooks and clean up imports

* feat(wallet-dashboard): move useStakeTxnInfo hook to the core

* fix(tooling-core): downgrade bignumber.js to 9.1.1 and yup to 1.1.1

* refactor(tooling-dashboard): change export to default and clean up code structure

* refactor(wallet-dashboard): simplify validator info retrieval and add utility for total stake calculation

* refactor(wallet-dashboard): streamline stake calculations and integrate new validator details utility

* refactor(wallet, core): update import paths for consistency and clarity

* refactor(wallet-dashboard): integrate FormikProvider. Polish interfaces.

* feat(wallet-dashboard): refactor staking dialog management for home

* feat(wallet-dashboard): move constants to another folder.

* feat(wallet-dashboard): enhance transaction handling and improve user feedback

* fix(wallet-dashboard): update onBack handler for improved navigation

* refactor(wallet-dashboard): simplify import paths by removing redundant index references

* fix(wallet-dashboard): update tooltip text for total staked information

* refactor(core): remove unused totalValidatorStake utility function

* feat(wallet-dashboard): add totalStakeOriginal to staking details and update calculations in UnstakeView

* refactor(wallet): remove debug log for coinBalance in UnstakeForm

---------

Co-authored-by: Bran <[email protected]>
Co-authored-by: JCNoguera <[email protected]>
Co-authored-by: cpl121 <[email protected]>
  • Loading branch information
4 people authored Nov 25, 2024
1 parent 15f6ea6 commit 3662450
Show file tree
Hide file tree
Showing 32 changed files with 860 additions and 274 deletions.
3 changes: 1 addition & 2 deletions apps/core/src/components/coin/CoinIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
// SPDX-License-Identifier: Apache-2.0

import React from 'react';
import { useCoinMetadata } from '../../hooks';
import { useCoinMetadata, ImageIcon, ImageIconSize } from '../../';
import { IotaLogoMark } from '@iota/ui-icons';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { ImageIcon, ImageIconSize } from '../icon';
import cx from 'clsx';

interface NonIotaCoinProps {
Expand Down
3 changes: 3 additions & 0 deletions apps/core/src/constants/staking.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ export const UNSTAKING_REQUEST_EVENT = '0x3::validator::UnstakingRequestEvent';

export const DELEGATED_STAKES_QUERY_STALE_TIME = 10_000;
export const DELEGATED_STAKES_QUERY_REFETCH_INTERVAL = 30_000;

export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE = 2;
export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS = 1;
2 changes: 2 additions & 0 deletions apps/core/src/hooks/stake/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
export * from './useGetDelegatedStake';
export * from './useTotalDelegatedRewards';
export * from './useTotalDelegatedStake';
export * from './useValidatorInfo';
export * from './useStakeTxnInfo';
52 changes: 52 additions & 0 deletions apps/core/src/hooks/stake/useStakeTxnInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import {
useGetTimeBeforeEpochNumber,
useTimeAgo,
TimeUnit,
NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE,
NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS,
} from '../../';

export function useStakeTxnInfo(startEpoch?: string | number) {
const startEarningRewardsEpoch =
Number(startEpoch || 0) + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS;

const redeemableRewardsEpoch =
Number(startEpoch || 0) + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE;

const { data: timeBeforeStakeRewardsStarts } =
useGetTimeBeforeEpochNumber(startEarningRewardsEpoch);
const timeBeforeStakeRewardsStartsAgo = useTimeAgo({
timeFrom: timeBeforeStakeRewardsStarts,
shortedTimeLabel: false,
shouldEnd: true,
maxTimeUnit: TimeUnit.ONE_HOUR,
});
const stakedRewardsStartEpoch =
timeBeforeStakeRewardsStarts > 0
? `in ${timeBeforeStakeRewardsStartsAgo}`
: startEpoch
? `Epoch #${Number(startEarningRewardsEpoch)}`
: '--';

const { data: timeBeforeStakeRewardsRedeemable } =
useGetTimeBeforeEpochNumber(redeemableRewardsEpoch);
const timeBeforeStakeRewardsRedeemableAgo = useTimeAgo({
timeFrom: timeBeforeStakeRewardsRedeemable,
shortedTimeLabel: false,
shouldEnd: true,
maxTimeUnit: TimeUnit.ONE_HOUR,
});
const timeBeforeStakeRewardsRedeemableAgoDisplay =
timeBeforeStakeRewardsRedeemable > 0
? `in ${timeBeforeStakeRewardsRedeemableAgo}`
: startEpoch
? `Epoch #${Number(redeemableRewardsEpoch)}`
: '--';

return {
stakedRewardsStartEpoch,
timeBeforeStakeRewardsRedeemableAgoDisplay,
};
}
50 changes: 50 additions & 0 deletions apps/core/src/hooks/stake/useValidatorInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import { useIotaClientQuery } from '@iota/dapp-kit';
import { useGetValidatorsApy } from '../';

export function useValidatorInfo({ validatorAddress }: { validatorAddress: string }) {
const {
data: system,
isPending: isPendingValidators,
isError: errorValidators,
} = useIotaClientQuery('getLatestIotaSystemState');
const { data: rollingAverageApys } = useGetValidatorsApy();

const validatorSummary =
system?.activeValidators.find((validator) => validator.iotaAddress === validatorAddress) ||
null;

const currentEpoch = Number(system?.epoch || 0);

const stakingPoolActivationEpoch = Number(validatorSummary?.stakingPoolActivationEpoch || 0);

// flag as new validator if the validator was activated in the last epoch
// for genesis validators, this will be false
const newValidator = currentEpoch - stakingPoolActivationEpoch <= 1 && currentEpoch !== 0;

// flag if the validator is at risk of being removed from the active set
const isAtRisk = system?.atRiskValidators.some((item) => item[0] === validatorAddress);

const { apy, isApyApproxZero } = rollingAverageApys?.[validatorAddress] ?? {
apy: null,
};

const commission = validatorSummary ? Number(validatorSummary.commissionRate) / 100 : 0;

return {
system,
isPendingValidators,
errorValidators,

currentEpoch,
validatorSummary,
name: validatorSummary?.name || '',
stakingPoolActivationEpoch,
commission,
newValidator,
isAtRisk,
apy,
isApyApproxZero,
};
}
1 change: 1 addition & 0 deletions apps/core/src/hooks/useGetStakingValidatorDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export function useGetStakingValidatorDetails({
return {
epoch: Number(system?.epoch) || 0,
totalStake: totalStakeFormatted,
totalStakeOriginal: totalStake,
totalValidatorsStake: totalValidatorsStakeFormatted,
totalStakePercentage,
validatorApy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Modifications Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { CoinFormat, formatBalance } from '@iota/core';
import { CoinFormat, formatBalance } from '../../';
import BigNumber from 'bignumber.js';
import { mixed, object } from 'yup';

Expand Down
1 change: 1 addition & 0 deletions apps/core/src/utils/stake/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './formatDelegatedStake';
export * from './createStakeTransaction';
export * from './createTimelockedUnstakeTransaction';
export * from './createTimelockedStakeTransaction';
export * from './createValidationSchema';
39 changes: 25 additions & 14 deletions apps/wallet-dashboard/app/(protected)/staking/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
'use client';

import { AmountBox, Box, StakeCard, StakeDialog, Button } from '@/components';
import { StakeDetailsDialog } from '@/components/Dialogs';
import { useStakeDialog } from '@/components/Dialogs/Staking/hooks/useStakeDialog';

import {
ExtendedDelegatedStake,
formatDelegatedStake,
Expand All @@ -17,12 +18,22 @@ import {
} from '@iota/core';
import { useCurrentAccount } from '@iota/dapp-kit';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { useState } from 'react';
import { StakeDialogView } from '@/components/Dialogs/Staking/StakeDialog';

function StakingDashboardPage(): JSX.Element {
const account = useCurrentAccount();
const [isDialogStakeOpen, setIsDialogStakeOpen] = useState(false);
const [selectedStake, setSelectedStake] = useState<ExtendedDelegatedStake | null>(null);

const {
isDialogStakeOpen,
stakeDialogView,
setStakeDialogView,
selectedStake,
setSelectedStake,
selectedValidator,
setSelectedValidator,
handleCloseStakeDialog,
handleNewStake,
} = useStakeDialog();

const { data: delegatedStakeData } = useGetDelegatedStake({
address: account?.address || '',
Expand All @@ -43,13 +54,10 @@ function StakingDashboardPage(): JSX.Element {
);

const viewStakeDetails = (extendedStake: ExtendedDelegatedStake) => {
setStakeDialogView(StakeDialogView.Details);
setSelectedStake(extendedStake);
};

function handleNewStake() {
setIsDialogStakeOpen(true);
}

return (
<>
<div className="flex flex-col items-center justify-center gap-4 pt-12">
Expand Down Expand Up @@ -79,12 +87,15 @@ function StakingDashboardPage(): JSX.Element {
</Box>
<Button onClick={handleNewStake}>New Stake</Button>
</div>
<StakeDialog isOpen={isDialogStakeOpen} setOpen={setIsDialogStakeOpen} />;
{selectedStake && (
<StakeDetailsDialog
extendedStake={selectedStake}
handleClose={() => setSelectedStake(null)}
showActiveStatus
{isDialogStakeOpen && stakeDialogView && (
<StakeDialog
stakedDetails={selectedStake}
isOpen={isDialogStakeOpen}
handleClose={handleCloseStakeDialog}
view={stakeDialogView}
setView={setStakeDialogView}
selectedValidator={selectedValidator}
setSelectedValidator={setSelectedValidator}
/>
)}
</>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 3662450

Please sign in to comment.