+
- {STATE_TO_COPY[state]}
+ {numberOfEpochPastRequesting > 2
+ ? 'Staking Reward'
+ : 'Starts Earning'}
- {!!rewards && (
-
+ {numberOfEpochPastRequesting <= 2 && (
+
+ Epoch #{delegationsRequestEpoch + 2}
+
+ )}
+
+ {rewards > 0 && numberOfEpochPastRequesting > 2 && (
+
{rewardsFormatted} SUI
)}
diff --git a/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx b/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx
index 134865bfb942a..b58c2151017b9 100644
--- a/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx
+++ b/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx
@@ -3,13 +3,14 @@
import { SUI_TYPE_ARG } from '@mysten/sui.js';
+import { Heading } from '_app/shared/heading';
import { Text } from '_app/shared/text';
import { useFormatCoin } from '_hooks';
//TODO unify StakeAmount and CoinBalance
interface StakeAmountProps {
balance: bigint | number | string;
- variant: 'heading4' | 'body';
+ variant: 'heading5' | 'body';
isEarnedRewards?: boolean;
}
@@ -23,20 +24,32 @@ export function StakeAmount({
const zeroBalanceColor = !!balance;
const earnRewardColor =
isEarnedRewards && (zeroBalanceColor ? 'success-dark' : 'gray-60');
- const colorAmount = variant === 'heading4' ? 'gray-90' : 'steel-darker';
- const colorSymbol = variant === 'heading4' ? 'steel' : 'steel-darker';
+ const colorAmount = variant === 'heading5' ? 'gray-90' : 'steel-darker';
+ const colorSymbol = variant === 'heading5' ? 'steel' : 'steel-darker';
return (
+ {variant === 'heading5' ? (
+
+ {formatted}
+
+ ) : (
+
+ {formatted}
+
+ )}
+
- {formatted}
-
-
diff --git a/apps/wallet/src/ui/app/staking/stake/StakeForm.tsx b/apps/wallet/src/ui/app/staking/stake/StakeForm.tsx
index 20f8fa6ac8384..461862ffe344e 100644
--- a/apps/wallet/src/ui/app/staking/stake/StakeForm.tsx
+++ b/apps/wallet/src/ui/app/staking/stake/StakeForm.tsx
@@ -141,7 +141,10 @@ function StakeForm({
weight="medium"
color="steel-darker"
>
- {unstake ? 0 : calculateRemaining} {symbol}
+ {calculateRemaining <= 0
+ ? 0
+ : calculateRemaining}{' '}
+ {symbol}
)}
diff --git a/apps/wallet/src/ui/app/staking/stake/ValidatorFormDetail.tsx b/apps/wallet/src/ui/app/staking/stake/ValidatorFormDetail.tsx
index 9c941e2223b6a..16b19a9ecf738 100644
--- a/apps/wallet/src/ui/app/staking/stake/ValidatorFormDetail.tsx
+++ b/apps/wallet/src/ui/app/staking/stake/ValidatorFormDetail.tsx
@@ -1,6 +1,6 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
-import { is, SuiObject, type ValidatorsFields } from '@mysten/sui.js';
+
import { useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
@@ -9,6 +9,7 @@ import { StakeAmount } from '../home/StakeAmount';
import { useGetDelegatedStake } from '../useGetDelegatedStake';
import { STATE_OBJECT } from '../usePendingDelegation';
import { ValidatorLogo } from '../validators/ValidatorLogo';
+import { validatorsFields } from '../validatorsFields';
import { Card } from '_app/shared/card';
import Alert from '_components/alert';
import LoadingIndicator from '_components/loading/LoadingIndicator';
@@ -32,7 +33,7 @@ export function ValidatorFormDetail({
const [searchParams] = useSearchParams();
const stakeIdParams = searchParams.get('staked');
const {
- data: validatetors,
+ data: validators,
isLoading: loadingValidators,
isError: errorValidators,
} = useGetObject(STATE_OBJECT);
@@ -44,22 +45,7 @@ export function ValidatorFormDetail({
error,
} = useGetDelegatedStake(accountAddress || '');
- const validatorsData =
- validatetors &&
- is(validatetors.details, SuiObject) &&
- validatetors.details.data.dataType === 'moveObject'
- ? (validatetors.details.data.fields as ValidatorsFields)
- : null;
-
- const delegationData = useMemo(() => {
- if (!allDelegation) return null;
-
- return allDelegation.find(
- ({ staked_sui }) => staked_sui.id.id === stakedId
- );
- }, [allDelegation, stakedId]);
-
- const totalSuiStake = delegationData?.staked_sui.principal.value || 0n;
+ const validatorsData = validatorsFields(validators);
const validatorData = useMemo(() => {
if (!validatorsData) return null;
@@ -68,7 +54,8 @@ export function ValidatorFormDetail({
);
}, [validatorAddress, validatorsData]);
- const totalValidatorStake = validatorData?.fields.stake_amount || 0;
+ const totalValidatorStake =
+ validatorData?.fields.delegation_staking_pool.fields.sui_balance || 0;
const totalStake = useMemo(() => {
if (!allDelegation) return 0n;
@@ -174,13 +161,10 @@ export function ValidatorFormDetail({
>
Total Staked
+
diff --git a/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx b/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx
index c3042374ff9de..a8f9e2d0871d3 100644
--- a/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx
+++ b/apps/wallet/src/ui/app/staking/validators/SelectValidatorCard.tsx
@@ -1,7 +1,6 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
-import { is, SuiObject, type ValidatorsFields } from '@mysten/sui.js';
import cl from 'classnames';
import { useState, useMemo } from 'react';
@@ -11,6 +10,7 @@ import { ValidatorListItem } from './ValidatorListItem';
import { Content, Menu } from '_app/shared/bottom-menu-layout';
import Button from '_app/shared/button';
import { Text } from '_app/shared/text';
+import { validatorsFields } from '_app/staking/validatorsFields';
import Alert from '_components/alert';
import Icon, { SuiIcons } from '_components/icon';
import LoadingIndicator from '_components/loading/LoadingIndicator';
@@ -21,16 +21,11 @@ export function SelectValidatorCard() {
null
);
const [sortKey, setSortKey] = useState<'name' | 'apy'>('apy');
- const [sortAscending, setSortAscending] = useState(true);
+ const [sortAscending, setSortAscending] = useState(false);
const { data, isLoading, isError } = useGetObject(STATE_OBJECT);
- const validatorsData =
- data &&
- is(data.details, SuiObject) &&
- data.details.data.dataType === 'moveObject'
- ? (data.details.data.fields as ValidatorsFields)
- : null;
+ const validatorsData = data && validatorsFields(data);
const selectValidator = (address: string) => {
setSelectedValidator((state) => (state !== address ? address : null));
@@ -118,8 +113,8 @@ export function SelectValidatorCard() {
className={cl(
'text-captionSmall font-thin text-hero',
sortAscending
- ? '-rotate-90'
- : 'rotate-90'
+ ? 'rotate-90'
+ : '-rotate-90'
)}
/>
)}
@@ -146,8 +141,8 @@ export function SelectValidatorCard() {
className={cl(
'text-captionSmall font-thin text-hero',
sortAscending
- ? '-rotate-90'
- : 'rotate-90'
+ ? 'rotate-90'
+ : '-rotate-90'
)}
/>
)}
diff --git a/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx b/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx
index 18f0a1d6b7646..94c38af18f2f7 100644
--- a/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx
+++ b/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx
@@ -4,9 +4,12 @@
import { useFeature } from '@growthbook/growthbook-react';
import { useMemo } from 'react';
+import { getStakingRewards } from '../getStakingRewards';
import { StakeAmount } from '../home/StakeAmount';
import { useGetDelegatedStake } from '../useGetDelegatedStake';
-import { DelegationCard, DelegationState } from './../home/DelegationCard';
+import { STATE_OBJECT } from '../usePendingDelegation';
+import { validatorsFields } from '../validatorsFields';
+import { DelegationCard } from './../home/DelegationCard';
import BottomMenuLayout, {
Menu,
Content,
@@ -17,36 +20,58 @@ import { Text } from '_app/shared/text';
import Alert from '_components/alert';
import Icon, { SuiIcons } from '_components/icon';
import LoadingIndicator from '_components/loading/LoadingIndicator';
-import { useAppSelector } from '_hooks';
+import { useAppSelector, useGetObject } from '_hooks';
import { FEATURES } from '_src/shared/experimentation/features';
export function ValidatorsCard() {
const accountAddress = useAppSelector(({ account }) => account.address);
const {
- data: stakeValidators,
+ data: delegations,
isLoading,
isError,
error,
} = useGetDelegatedStake(accountAddress || '');
+ const { data: validators } = useGetObject(STATE_OBJECT);
+
+ const validatorsData = validators && validatorsFields(validators);
+
+ const activeValidators =
+ validatorsData?.validators.fields.active_validators;
+ // Total earn token for all delegations
+ const totalEarnToken = useMemo(() => {
+ if (!delegations || !validatorsData) return 0;
+
+ const activeValidators =
+ validatorsData.validators.fields.active_validators;
+
+ return delegations.reduce(
+ (acc, delegation) =>
+ acc + getStakingRewards(activeValidators, delegation),
+ 0
+ );
+ }, [delegations, validatorsData]);
+
+ // Total active stake for all delegations
+
const totalActivePendingStake = useMemo(() => {
- if (!stakeValidators) return 0n;
- return stakeValidators.reduce(
+ if (!delegations) return 0n;
+ return delegations.reduce(
(acc, { staked_sui }) => acc + BigInt(staked_sui.principal.value),
0n
);
- }, [stakeValidators]);
+ }, [delegations]);
const numberOfValidators = useMemo(() => {
- if (!stakeValidators) return 0;
+ if (!delegations) return 0;
return [
...new Set(
- stakeValidators.map(
+ delegations.map(
({ staked_sui }) => staked_sui.validator_address
)
),
].length;
- }, [stakeValidators]);
+ }, [delegations]);
const stakingEnabled = useFeature(FEATURES.STAKING_ENABLED).on;
@@ -69,7 +94,7 @@ export function ValidatorsCard() {
}
return (
-
+
@@ -94,13 +119,13 @@ export function ValidatorsCard() {
@@ -108,22 +133,16 @@ export function ValidatorsCard() {
- {stakeValidators.map(
- ({ delegation_status, staked_sui }) => (
+ {validatorsData &&
+ activeValidators &&
+ delegations.map((delegationObject) => (
- )
- )}
+ ))}
diff --git a/apps/wallet/src/ui/app/staking/validatorsFields.ts b/apps/wallet/src/ui/app/staking/validatorsFields.ts
new file mode 100644
index 0000000000000..d986ff21cf9f2
--- /dev/null
+++ b/apps/wallet/src/ui/app/staking/validatorsFields.ts
@@ -0,0 +1,19 @@
+// Copyright (c) Mysten Labs, Inc.
+// SPDX-License-Identifier: Apache-2.0
+
+import {
+ is,
+ SuiObject,
+ type ValidatorsFields,
+ type GetObjectDataResponse,
+} from '@mysten/sui.js';
+
+export function validatorsFields(
+ data?: GetObjectDataResponse
+): ValidatorsFields | null {
+ return data &&
+ is(data.details, SuiObject) &&
+ data.details.data.dataType === 'moveObject'
+ ? (data.details.data.fields as ValidatorsFields)
+ : null;
+}