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(wallet-dashboard): add staking confirmation screen #4034

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c925a99
feat(tooling-dashboard): style selected stake
panteleymonchuk Oct 31, 2024
1d8887e
feat(tooling-dashboard): add data to stake details page
panteleymonchuk Oct 31, 2024
a852fab
feat(wallet-dashboard): remove extra memo.
panteleymonchuk Nov 1, 2024
8325b36
Merge remote-tracking branch 'origin/develop' into tooling-dashboard/…
panteleymonchuk Nov 7, 2024
388058c
feat(staking): refactor StakeDialog. Add new Layout component.
panteleymonchuk Nov 7, 2024
d8d03ac
feat(tooling-core): add clsx dependency to package.json and update pn…
panteleymonchuk Nov 7, 2024
1ff40ea
Merge remote-tracking branch 'origin/develop' into tooling-dashboard/…
panteleymonchuk Nov 7, 2024
2c1adc9
Merge remote-tracking branch 'origin/tooling-epic/dashboard-styling' …
panteleymonchuk Nov 13, 2024
4d93394
feat(wallet-dashboard): manage view for dialog outside.
panteleymonchuk Nov 13, 2024
8c17341
feat(wallet-dashboard): join changes from PR 3854
panteleymonchuk Nov 13, 2024
7f66cd0
feat(wallet-dashboard): join enter amount screen from PR 3874
panteleymonchuk Nov 13, 2024
5932ed5
feat(tooling-core): move validation schema
panteleymonchuk Nov 14, 2024
1507c81
feat(wallet-dashboard): add staking confirmation screen
VmMad Nov 14, 2024
9bdb887
feat(wallet-dashboard): integrate Formik
panteleymonchuk Nov 14, 2024
499e4a6
fix: build error
VmMad Nov 14, 2024
14a2786
feat(wallet-dashboard): enhance StakeDialog and EnterAmountView with …
panteleymonchuk Nov 14, 2024
c1341dc
feat(wallet-dashboard): update StakeDialog to support selectedValidat…
panteleymonchuk Nov 14, 2024
c4329f4
feat(wallet-dashboard): refactor StakedInfo and Validator components …
panteleymonchuk Nov 14, 2024
3a4ebb7
feat(wallet-dashboard): move useStakeTxnInfo hook to the core
panteleymonchuk Nov 15, 2024
3818f2c
Merge branch 'tooling-dashboard/style-selected-stake' into tooling-da…
VmMad Nov 15, 2024
54b1b1f
fix(tooling-core): downgrade bignumber.js to 9.1.1 and yup to 1.1.1
panteleymonchuk Nov 15, 2024
4777432
feat: add new layout
VmMad Nov 15, 2024
b13ac91
Merge branch 'tooling-dashboard/style-selected-stake' into tooling-da…
VmMad Nov 15, 2024
8242185
refactor(tooling-dashboard): change export to default and clean up co…
panteleymonchuk Nov 15, 2024
cc8b8c6
Merge branch 'tooling-dashboard/style-selected-stake' into tooling-da…
VmMad Nov 18, 2024
d5ee9a1
fix: import
VmMad Nov 18, 2024
47cbd98
refactor: rename button and view
VmMad Nov 19, 2024
371b2fd
Merge branch 'tooling-epic/dashboard-styling' into tooling-dashboard/…
brancoder Nov 19, 2024
be3b938
refactor(wallet-dashboard): simplify validator info retrieval and add…
panteleymonchuk Nov 19, 2024
80049ac
refactor(wallet-dashboard): streamline stake calculations and integra…
panteleymonchuk Nov 19, 2024
24144b3
Merge remote-tracking branch 'origin/tooling-epic/dashboard-styling' …
panteleymonchuk Nov 20, 2024
0cfd637
refactor(wallet, core): update import paths for consistency and clarity
panteleymonchuk Nov 20, 2024
dc99beb
refactor(wallet-dashboard): integrate FormikProvider. Polish interfaces.
panteleymonchuk Nov 20, 2024
8b2df8f
Merge branch 'tooling-dashboard/style-selected-stake' into tooling-da…
VmMad Nov 21, 2024
873a5aa
refactor: update component name
VmMad Nov 21, 2024
a6e664b
Merge remote-tracking branch 'origin/develop' into tooling-dashboard/…
panteleymonchuk Nov 21, 2024
2afa4d8
Merge branch 'develop' into tooling-dashboard/style-selected-stake
brancoder Nov 22, 2024
796bf46
refactor: improve props
VmMad Nov 22, 2024
bcbdebd
feat(wallet-dashboard): refactor staking dialog management for home
panteleymonchuk Nov 22, 2024
b964e75
feat(wallet-dashboard): move constants to another folder.
panteleymonchuk Nov 22, 2024
c8bbc90
feat(wallet-dashboard): enhance transaction handling and improve user…
panteleymonchuk Nov 22, 2024
af7f7dc
fix(wallet-dashboard): update onBack handler for improved navigation
panteleymonchuk Nov 22, 2024
69bcf98
Merge branch 'develop' into tooling-dashboard/style-selected-stake
VmMad Nov 22, 2024
ce38b84
Merge branch 'tooling-dashboard/style-selected-stake' into tooling-da…
VmMad Nov 25, 2024
24ea08c
Merge branch 'develop' into tooling-dashboard/style-confirmation-screen
VmMad Nov 25, 2024
8c14776
fix: update coin image
VmMad Nov 25, 2024
9f7fe1d
refactor: remove debris
VmMad Nov 26, 2024
026ee47
Merge branch 'develop' into tooling-dashboard/style-confirmation-screen
VmMad Nov 26, 2024
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
1 change: 1 addition & 0 deletions apps/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@sentry/react": "^7.59.2",
"@tanstack/react-query": "^5.50.1",
"bignumber.js": "^9.1.1",
"clsx": "^2.1.1",
"qrcode.react": "^4.0.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
1 change: 1 addition & 0 deletions apps/core/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

export * from './KioskClientProvider';
export * from './QR';
export * from './image-icon';
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';
49 changes: 49 additions & 0 deletions apps/core/src/hooks/stake/useStakeTxnInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import { useGetTimeBeforeEpochNumber, useTimeAgo, TimeUnit } from '../../index';

export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE = 2;
export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS = 1;

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
? `${timeBeforeStakeRewardsStartsAgo === '--' ? '' : '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
? `${timeBeforeStakeRewardsRedeemableAgo === '--' ? '' : 'in'} ${timeBeforeStakeRewardsRedeemableAgo}`
: startEpoch
? `Epoch #${Number(redeemableRewardsEpoch)}`
: '--';

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

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

const validatorSummary = useMemo(() => {
if (!system) return null;

return (
system.activeValidators.find(
(validator) => validator.iotaAddress === validatorAddress,
) || null
);
}, [validatorAddress, system]);

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

//TODO: verify this is the correct validator stake balance
const totalValidatorStake = validatorSummary?.stakingPoolIotaBalance || 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,
};

return {
system,
validatorSummary,
name: validatorSummary?.name || '',
stakingPoolActivationEpoch,
commission: validatorSummary ? Number(validatorSummary.commissionRate) / 100 : 0,
newValidator,
isAtRisk,
apy,
isApyApproxZero,
totalValidatorStake,
};
}
10 changes: 6 additions & 4 deletions apps/core/src/hooks/useGetValidatorsApy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import { roundFloat } from '../utils/roundFloat';

const DEFAULT_APY_DECIMALS = 2;

export interface ValidatorApyData {
apy: number;
isApyApproxZero: boolean;
}

export interface ApyByValidator {
[validatorAddress: string]: {
apy: number;
isApyApproxZero: boolean;
};
[validatorAddress: string]: ValidatorApyData;
}
// For small APY, show ~0% instead of 0%
// If APY falls below 0.001, show ~0% instead of 0% since we round to 2 decimal places
Expand Down
6 changes: 6 additions & 0 deletions apps/core/src/utils/formatApy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export function formatApy(apy: number, isApyApproxZero: boolean = false): string {
return isApyApproxZero ? '~0%' : `${apy}%`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return isApyApproxZero ? '~0%' : `${apy}%`;
return isApyApproxZero ? '~ 0%' : `${apy}%`;

}
1 change: 1 addition & 0 deletions apps/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export * from './getDelegationDataByStakeId';
export * from './api-env';
export * from './getExplorerPaths';
export * from './getExplorerLink';
export * from './formatApy';

export * from './stake';
export * from './transaction';
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 '../../index';
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';
4 changes: 2 additions & 2 deletions apps/ui-kit/src/lib/components/organisms/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<
>(({ showCloseIcon, ...props }, ref) => (
<RadixDialog.Overlay
ref={ref}
className="absolute inset-0 z-[99998] bg-shader-neutral-light-48 backdrop-blur-md"
className="fixed inset-0 z-[99998] bg-shader-neutral-light-48 backdrop-blur-md"
{...props}
>
<DialogClose className={cx('fixed right-3 top-3', { hidden: !showCloseIcon })}>
Expand Down Expand Up @@ -70,7 +70,7 @@ const DialogContent = React.forwardRef<
<RadixDialog.Content
ref={ref}
className={cx(
'absolute z-[99999] flex flex-col justify-center overflow-hidden bg-primary-100 dark:bg-neutral-6 md:w-96',
'fixed z-[99999] flex flex-col justify-center overflow-hidden bg-primary-100 dark:bg-neutral-6 md:w-96',
positionClass,
)}
{...props}
Expand Down
33 changes: 23 additions & 10 deletions apps/wallet-dashboard/app/(protected)/staking/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
'use client';

import { AmountBox, Box, StakeCard, StakeDialog, Button } from '@/components';
import { StakeDetailsDialog } from '@/components/Dialogs';
import { StakeDialogView } from '@/components/Dialogs/Staking/StakeDialog';
import {
ExtendedDelegatedStake,
formatDelegatedStake,
Expand All @@ -21,9 +21,9 @@ import { useState } from 'react';

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

const [selectedValidator, setSelectedValidator] = useState<string>('');
const { data: delegatedStakeData } = useGetDelegatedStake({
address: account?.address || '',
staleTime: DELEGATED_STAKES_QUERY_STALE_TIME,
Expand All @@ -43,13 +43,23 @@ function StakingDashboardPage(): JSX.Element {
);

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

function handleCloseStakeDialog() {
setSelectedValidator('');
setSelectedStake(null);
setStakeDialogView(undefined);
}

function handleNewStake() {
setIsDialogStakeOpen(true);
setSelectedStake(null);
setStakeDialogView(StakeDialogView.SelectValidator);
}

const isDialogStakeOpen = stakeDialogView !== undefined;

return (
<>
<div className="flex flex-col items-center justify-center gap-4 pt-12">
Expand Down Expand Up @@ -79,12 +89,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 && (
<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
Loading