diff --git a/apps/ui-kit/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx b/apps/ui-kit/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx
index a9bb2b7f224..972a53873bc 100644
--- a/apps/ui-kit/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx
+++ b/apps/ui-kit/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx
@@ -43,7 +43,7 @@ export function KeyValueInfo({
}: KeyValueProps): React.JSX.Element {
return (
-
+
{keyText}
{showInfoIcon && }
diff --git a/apps/wallet/src/ui/app/components/Overlay.tsx b/apps/wallet/src/ui/app/components/Overlay.tsx
index 5ef8e66b7f5..c90090de085 100644
--- a/apps/wallet/src/ui/app/components/Overlay.tsx
+++ b/apps/wallet/src/ui/app/components/Overlay.tsx
@@ -6,6 +6,7 @@ import { useCallback } from 'react';
import type { ReactNode } from 'react';
import { Header } from '@iota/apps-ui-kit';
import { Portal } from '../shared/Portal';
+import { useNavigate } from 'react-router-dom';
interface OverlayProps {
title?: string;
@@ -15,9 +16,17 @@ interface OverlayProps {
closeIcon?: ReactNode | null;
setShowModal?: (showModal: boolean) => void;
background?: 'bg-iota-lightest';
+ showBackButton?: boolean;
}
-export function Overlay({ title, children, showModal, closeOverlay, setShowModal }: OverlayProps) {
+export function Overlay({
+ title,
+ children,
+ showModal,
+ closeOverlay,
+ showBackButton,
+ setShowModal,
+}: OverlayProps) {
const closeModal = useCallback(
(e: React.MouseEvent
) => {
closeOverlay && closeOverlay();
@@ -25,11 +34,19 @@ export function Overlay({ title, children, showModal, closeOverlay, setShowModal
},
[closeOverlay, setShowModal],
);
-
+ const navigate = useNavigate();
+ const handleBack = useCallback(() => navigate(-1), [navigate]);
return showModal ? (
- {title &&
}
+ {title && (
+
+ )}
{children}
diff --git a/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx b/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx
index 30cc6dd52d9..fd696e387f6 100644
--- a/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx
+++ b/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx
@@ -2,17 +2,10 @@
// Modifications Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
-import BottomMenuLayout, { Content } from '_app/shared/bottom-menu-layout';
-import { Button } from '_app/shared/ButtonUI';
-import { Card } from '_app/shared/card';
-import { CardItem } from '_app/shared/card/CardItem';
-import { Text } from '_app/shared/text';
-import { IconTooltip } from '_app/shared/tooltip';
import { Alert, LoadingIndicator } from '_components';
import { useAppSelector } from '_hooks';
import { ampli } from '_src/shared/analytics/ampli';
import { MIN_NUMBER_IOTA_TO_STAKE } from '_src/shared/constants';
-import FaucetRequestButton from '_src/ui/app/shared/faucet/FaucetRequestButton';
import {
useBalance,
useCoinMetadata,
@@ -20,18 +13,30 @@ import {
useGetValidatorsApy,
DELEGATED_STAKES_QUERY_REFETCH_INTERVAL,
DELEGATED_STAKES_QUERY_STALE_TIME,
+ useFormatCoin,
+ formatPercentageDisplay,
} from '@iota/core';
import { useIotaClientQuery } from '@iota/dapp-kit';
-import { ArrowLeft16, StakeAdd16, StakeRemove16 } from '@iota/icons';
import { Network, type StakeObject } from '@iota/iota-sdk/client';
-import { NANO_PER_IOTA, IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
+import { NANO_PER_IOTA, IOTA_TYPE_ARG, formatAddress } from '@iota/iota-sdk/utils';
import BigNumber from 'bignumber.js';
import { useMemo } from 'react';
import { useActiveAddress } from '../../hooks/useActiveAddress';
-import { Heading } from '../../shared/heading';
import { getDelegationDataByStakeId } from '../getDelegationByStakeId';
-import { StakeAmount } from '../home/StakeAmount';
+import {
+ CardImage,
+ CardBody,
+ Card,
+ CardType,
+ Panel,
+ KeyValueInfo,
+ Divider,
+ Button,
+ ButtonType,
+} from '@iota/apps-ui-kit';
+import { ImageIcon } from '../../shared/image-icon';
+import { useNavigate } from 'react-router-dom';
interface DelegationDetailCardProps {
validatorAddress: string;
@@ -39,6 +44,7 @@ interface DelegationDetailCardProps {
}
export function DelegationDetailCard({ validatorAddress, stakedId }: DelegationDetailCardProps) {
+ const navigate = useNavigate();
const {
data: system,
isPending: loadingValidators,
@@ -81,7 +87,6 @@ export function DelegationDetailCard({ validatorAddress, stakedId }: DelegationD
}, [allDelegation, stakedId]);
const totalStake = BigInt(delegationData?.principal || 0n);
-
const iotaEarned = BigInt(
(delegationData as Extract)?.estimatedReward ||
0n,
@@ -90,6 +95,9 @@ export function DelegationDetailCard({ validatorAddress, stakedId }: DelegationD
apy: 0,
};
+ const [iotaEarnedFormatted, iotaEarnedSymbol] = useFormatCoin(iotaEarned, IOTA_TYPE_ARG);
+ const [totalStakeFormatted, totalStakeSymbol] = useFormatCoin(totalStake, IOTA_TYPE_ARG);
+
const delegationId = delegationData?.status === 'Active' && delegationData?.stakedIotaId;
const stakeByValidatorAddress = `/stake/new?${new URLSearchParams({
@@ -122,167 +130,90 @@ export function DelegationDetailCard({ validatorAddress, stakedId }: DelegationD
);
}
- return (
-
-
-
-
- {hasInactiveValidatorDelegation ? (
-
-
- Unstake IOTA from this inactive validator and stake on an active
- validator to start earning rewards again.
-
-
- ) : null}
-
-
-
-
-
-
-
-
-
-
- }
- padding="none"
- >
-
- }
- >
-
-
- {isApyApproxZero ? '~' : ''}
- {apy}
-
-
-
- %
-
-
-
-
-
- Commission
-
-
-
-
- }
- >
-
-
- {commission}
-
+ if (hasInactiveValidatorDelegation) {
+
+
+ Unstake IOTA from this inactive validator and stake on an active validator to start
+ earning rewards again.
+
+
;
+ }
-
- %
-
-
-
-
-
-
-
- {!hasInactiveValidatorDelegation ? (
- }
- text="Stake IOTA"
- onClick={() => {
- ampli.clickedStakeIota({
- isCurrentlyStaking: true,
- sourceFlow: 'Delegation detail card',
- });
- }}
- disabled={showRequestMoreIotaToken}
- />
- ) : null}
+ function handleAddNewStake() {
+ navigate(stakeByValidatorAddress);
+ ampli.clickedStakeIota({
+ isCurrentlyStaking: true,
+ sourceFlow: 'Delegation detail card',
+ });
+ }
- {Boolean(totalStake) && delegationId && (
-
-
-
+ function handleUnstake() {
+ navigate(stakeByValidatorAddress + '&unstake=true');
+ ampli.clickedUnstakeIota({
+ stakedAmount: Number(totalStake / NANO_PER_IOTA),
+ validatorAddress,
+ });
+ }
- {/* show faucet request button on devnet or testnet whenever there is only one coin */}
- {showRequestMoreIotaToken ? (
-
-
-
- You need a minimum of {MIN_NUMBER_IOTA_TO_STAKE} IOTA to continue
- staking.
-
-
-
+ return (
+
+
+
+
+
+
+
+
+
+
- ) : (
+
+
+
+ {Boolean(totalStake) && delegationId && (
}
- text="Back"
+ type={ButtonType.Secondary}
+ onClick={handleUnstake}
+ text="Unstake"
+ fullWidth
/>
)}
-
+ {!hasInactiveValidatorDelegation ? (
+
+ ) : null}
+
);
}
diff --git a/apps/wallet/src/ui/app/staking/delegation-detail/index.tsx b/apps/wallet/src/ui/app/staking/delegation-detail/index.tsx
index 98f9e7a48df..d51ec4e4fe0 100644
--- a/apps/wallet/src/ui/app/staking/delegation-detail/index.tsx
+++ b/apps/wallet/src/ui/app/staking/delegation-detail/index.tsx
@@ -7,7 +7,6 @@ import { useGetDelegatedStake } from '@iota/core';
import { Navigate, useNavigate, useSearchParams } from 'react-router-dom';
import { useActiveAddress } from '../../hooks/useActiveAddress';
import { DelegationDetailCard } from './DelegationDetailCard';
-import { formatAddress } from '@iota/iota-sdk/utils';
export function DelegationDetail() {
const [searchParams] = useSearchParams();
@@ -20,7 +19,7 @@ export function DelegationDetail() {
});
if (!validatorAddressParams || !stakeIdParams) {
- return
;
+ return
;
}
if (isPending) {
@@ -32,12 +31,7 @@ export function DelegationDetail() {
}
return (
-
navigate('/')}
- >
+ navigate('/')}>