diff --git a/packages/components/src/components/Image/images.ts b/packages/components/src/components/Image/images.ts index 5c8615037e..9390e50810 100644 --- a/packages/components/src/components/Image/images.ts +++ b/packages/components/src/components/Image/images.ts @@ -16,6 +16,7 @@ export const IMAGES = { GAINS_GRAPH: 'gains-graph.svg', GHOST: 'ghost.svg', INVITY_LOGO: 'invity-logo.svg', + MORPHO_LOGO: 'morpho-logo.svg', PLAY_STORE: 'play-store.svg', RECOVERY_2x: 'recovery@2x.png', STROKE_BORDER: 'stroke-border.svg', diff --git a/packages/suite-data/files/images/images/morpho-logo.svg b/packages/suite-data/files/images/images/morpho-logo.svg new file mode 100644 index 0000000000..1fae6f4ce2 --- /dev/null +++ b/packages/suite-data/files/images/images/morpho-logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/packages/suite/src/actions/suite/constants/suiteConstants.ts b/packages/suite/src/actions/suite/constants/suiteConstants.ts index 3dd25b2c3f..d8bcb06306 100644 --- a/packages/suite/src/actions/suite/constants/suiteConstants.ts +++ b/packages/suite/src/actions/suite/constants/suiteConstants.ts @@ -16,7 +16,6 @@ export const TOR_BOOTSTRAP = '@suite/tor-bootstrap'; export const ONION_LINKS = '@suite/onion-links'; export const APP_CHANGED = '@suite/app-changed'; export const SET_THEME = '@suite/set-theme'; -export const SET_STAKING_DASHBOARD_COLLAPSED = '@suite/set-staking-dashboard-collapsed'; export const SET_SEND_FORM_PREFILL = '@suite/set-send-form-prefill'; export const SET_TRANSACTION_HISTORY_PREFILL = '@suite/set-transaction-history-prefill'; export const SET_ADDRESS_DISPLAY_TYPE = '@suite/set-display-address-type'; diff --git a/packages/suite/src/actions/suite/storageActions.ts b/packages/suite/src/actions/suite/storageActions.ts index 3034a80da4..13ab80f288 100644 --- a/packages/suite/src/actions/suite/storageActions.ts +++ b/packages/suite/src/actions/suite/storageActions.ts @@ -107,7 +107,6 @@ const removeCoinjoinRelatedSetting = (state: AppState) => { evmSettings: state.suite.evmSettings, seenDisconnectNotificationForDeviceIds: state.suite.seenDisconnectNotificationForDeviceIds, - stakingDashboardCollapsed: state.suite.stakingDashboardCollapsed, }, 'suite', true, @@ -394,7 +393,6 @@ export const saveSuiteSettings = evmSettings: suite.evmSettings, seenDisconnectNotificationForDeviceIds: suite.seenDisconnectNotificationForDeviceIds, - stakingDashboardCollapsed: suite.stakingDashboardCollapsed, }, 'suite', true, diff --git a/packages/suite/src/actions/suite/suiteActions.ts b/packages/suite/src/actions/suite/suiteActions.ts index 2a0187860a..f167f0da0f 100644 --- a/packages/suite/src/actions/suite/suiteActions.ts +++ b/packages/suite/src/actions/suite/suiteActions.ts @@ -81,10 +81,6 @@ export type SuiteAction = type: typeof SUITE.SET_THEME; variant: AppState['suite']['settings']['theme']['variant']; } - | { - type: typeof SUITE.SET_STAKING_DASHBOARD_COLLAPSED; - isCollapsed: boolean; - } | { type: typeof SUITE.SET_TRANSACTION_HISTORY_PREFILL; payload: string; @@ -127,11 +123,6 @@ export const setTheme = ( variant, }); -export const setStakingDashboardCollapsed = (isCollapsed: boolean): SuiteAction => ({ - type: SUITE.SET_STAKING_DASHBOARD_COLLAPSED, - isCollapsed, -}); - export const setAddressDisplayType = ( option: AppState['suite']['settings']['addressDisplayType'], ): SuiteAction => ({ diff --git a/packages/suite/src/components/earn/EarnDashboard/EarnDashboard.tsx b/packages/suite/src/components/earn/EarnDashboard/EarnDashboard.tsx new file mode 100644 index 0000000000..9a1e3b70f3 --- /dev/null +++ b/packages/suite/src/components/earn/EarnDashboard/EarnDashboard.tsx @@ -0,0 +1,19 @@ +import { Column } from '@trezor/components'; + +import { useSelector } from 'src/hooks/suite'; +import { selectRouteName } from 'src/reducers/suite/routerReducer'; + +import { EarnStakingTable } from './staking/EarnStakingTable'; +import { EarnYieldTable } from './yield/EarnYieldTable'; + +export const EarnDashboard = () => { + const routeName = useSelector(selectRouteName); + const isOnEarnPage = routeName === 'suite-earn'; + + return ( + + + {isOnEarnPage && } + + ); +}; diff --git a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountCell.tsx b/packages/suite/src/components/earn/EarnDashboard/common/EarnAccountCell.tsx similarity index 81% rename from packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountCell.tsx rename to packages/suite/src/components/earn/EarnDashboard/common/EarnAccountCell.tsx index c676530f45..80881636af 100644 --- a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountCell.tsx +++ b/packages/suite/src/components/earn/EarnDashboard/common/EarnAccountCell.tsx @@ -4,7 +4,7 @@ import { NetworkSymbol, getNetwork } from '@suite-common/wallet-config'; import { Account } from '@suite-common/wallet-types'; import { Column } from '@trezor/components'; import { CoinLogo } from '@trezor/product-components'; -import { spacings, spacingsPx, typography } from '@trezor/theme'; +import { spacingsPx, typography } from '@trezor/theme'; import { AccountLabel, CoinBalance } from 'src/components/suite'; @@ -25,15 +25,12 @@ const AccountLabelContainer = styled.div` white-space: nowrap; `; -interface StakingDashboardAccountCellProps { +type EarnAccountCellProps = { account?: Account; symbol?: NetworkSymbol; -} +}; -export const StakingDashboardAccountCell = ({ - account, - symbol, -}: StakingDashboardAccountCellProps) => { +export const EarnAccountCell = ({ account, symbol }: EarnAccountCellProps) => { const networkSymbol = account?.symbol ?? symbol; if (!networkSymbol) return null; @@ -41,10 +38,10 @@ export const StakingDashboardAccountCell = ({ return ( - + - + {account ? ( ; + children: ReactNode; +}; + +export const EarnDashboardSection = ({ + titleId, + subheadingId, + provider, + statusBadge, + sectionRef, + children, +}: EarnDashboardSectionProps) => { + const routeName = useSelector(selectRouteName); + const isOnEarnPage = routeName === 'suite-earn'; + const actions = isOnEarnPage && provider ? : undefined; + + return ( + + + {statusBadge && ( + + + + )} + + } + subheading={} + actions={actions} + ref={sectionRef} + > + {children} + + ); +}; diff --git a/packages/suite/src/components/earn/EarnDashboard/common/EarnDashboardTableHeader.tsx b/packages/suite/src/components/earn/EarnDashboard/common/EarnDashboardTableHeader.tsx new file mode 100644 index 0000000000..61e40c4006 --- /dev/null +++ b/packages/suite/src/components/earn/EarnDashboard/common/EarnDashboardTableHeader.tsx @@ -0,0 +1,31 @@ +import { Translation } from '@suite/intl'; +import { Table } from '@trezor/components'; + +type EarnDashboardTableHeaderProps = { + showRewardsColumns?: boolean; +}; + +export const EarnDashboardTableHeader = ({ + showRewardsColumns = true, +}: EarnDashboardTableHeaderProps) => ( + + + + + + + + + + {showRewardsColumns && } + + + {showRewardsColumns && ( + + )} + + {/* Actions column */} + + + +); diff --git a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardRewardsAmount.tsx b/packages/suite/src/components/earn/EarnDashboard/common/EarnRewardsAmount.tsx similarity index 69% rename from packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardRewardsAmount.tsx rename to packages/suite/src/components/earn/EarnDashboard/common/EarnRewardsAmount.tsx index a5661032ca..e19adf30c3 100644 --- a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardRewardsAmount.tsx +++ b/packages/suite/src/components/earn/EarnDashboard/common/EarnRewardsAmount.tsx @@ -3,32 +3,27 @@ import { useFormatters } from '@suite-common/formatters'; import { NetworkSymbol } from '@suite-common/wallet-config'; import { H4, TextVariant } from '@trezor/components'; -interface StakingDashboardRewardsAmountProps { - accountSymbol: NetworkSymbol; +type EarnRewardsAmountProps = { + symbol: NetworkSymbol; rewards: string; apy: number | null; variant?: TextVariant; -} +}; -export const StakingDashboardRewardsAmount = ({ - accountSymbol, - rewards, - apy, - variant, -}: StakingDashboardRewardsAmountProps) => { +export const EarnRewardsAmount = ({ symbol, rewards, apy, variant }: EarnRewardsAmountProps) => { const { CryptoAmountFormatter } = useFormatters(); if (!apy) return (

- +

); return (

{CryptoAmountFormatter.format(rewards, { - symbol: accountSymbol, + symbol, isBalance: true, withSymbol: true, isEllipsisAppended: false, diff --git a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsx b/packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingAccountRow.tsx similarity index 91% rename from packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsx rename to packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingAccountRow.tsx index 2c233beea2..f6a7cfd964 100644 --- a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsx +++ b/packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingAccountRow.tsx @@ -28,10 +28,10 @@ import { useAnalytics } from 'src/support/useAnalytics'; import { ApyValue } from 'src/views/wallet/staking/components/ApyValue'; import { formatApyValue } from 'src/views/wallet/staking/utils/formatStakeValues'; -import { StakingDashboardAccountCell } from './StakingDashboardAccountCell'; -import { StakingDashboardRewardsAmount } from './StakingDashboardRewardsAmount'; +import { EarnAccountCell } from '../common/EarnAccountCell'; +import { EarnRewardsAmount } from '../common/EarnRewardsAmount'; -export const StakingDashboardAccountRow = ({ account }: { account: Account }) => { +export const EarnStakingAccountRow = ({ account }: { account: Account }) => { const dispatch = useDispatch(); const { CryptoAmountFormatter } = useFormatters(); const analytics = useAnalytics(); @@ -155,8 +155,8 @@ export const StakingDashboardAccountRow = ({ account }: { account: Account }) => - @@ -164,7 +164,7 @@ export const StakingDashboardAccountRow = ({ account }: { account: Account }) => {isStakingActive && ( {apy && ( - {!isCardanoNetworkType && apy && ( return ( - + @@ -234,7 +234,7 @@ export const StakingDashboardAccountRow = ({ account }: { account: Account }) => @@ -281,7 +281,7 @@ export const StakingDashboardAccountRow = ({ account }: { account: Account }) => - + @@ -305,7 +305,7 @@ export const StakingDashboardAccountRow = ({ account }: { account: Account }) => diff --git a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx b/packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingActivateRow.tsx similarity index 86% rename from packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx rename to packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingActivateRow.tsx index 163b413a75..c8cb53607a 100644 --- a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx +++ b/packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingActivateRow.tsx @@ -8,9 +8,9 @@ import { openModal } from 'src/actions/suite/modalActions'; import { useDevice, useDispatch, useSelector } from 'src/hooks/suite'; import { ApyValue } from 'src/views/wallet/staking/components/ApyValue'; -import { StakingDashboardAccountCell } from './StakingDashboardAccountCell'; +import { EarnAccountCell } from '../common/EarnAccountCell'; -export const StakingDashboardActivateRow = ({ symbol }: { symbol: NetworkSymbol }) => { +export const EarnStakingActivateRow = ({ symbol }: { symbol: NetworkSymbol }) => { const dispatch = useDispatch(); const { device } = useDevice(); const apy = useSelector(state => selectPoolStatsApyData(state, undefined, symbol)); @@ -38,7 +38,7 @@ export const StakingDashboardActivateRow = ({ symbol }: { symbol: NetworkSymbol return ( - + @@ -48,7 +48,7 @@ export const StakingDashboardActivateRow = ({ symbol }: { symbol: NetworkSymbol diff --git a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx b/packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingTable.tsx similarity index 57% rename from packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx rename to packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingTable.tsx index 2a4647c428..4feb9a543e 100644 --- a/packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx +++ b/packages/suite/src/components/earn/EarnDashboard/staking/EarnStakingTable.tsx @@ -1,4 +1,3 @@ -import { Translation, TranslationKey } from '@suite/intl'; import { NetworkSymbol, StakingNetworkSymbol } from '@suite-common/wallet-config'; import { selectAccountIsStakingActive, @@ -15,45 +14,20 @@ import { isCardanoStakedWithFiveBinaries, toFiatCurrency, } from '@suite-common/wallet-utils'; -import { Badge, BadgeIntent, Card, Table } from '@trezor/components'; +import { Card, Table } from '@trezor/components'; import { BigNumber, arrayPartition } from '@trezor/utils'; -import { setStakingDashboardCollapsed } from 'src/actions/suite/suiteActions'; import { OutlineHighlight } from 'src/components/OutlineHighlight'; -import { DashboardSection } from 'src/components/dashboard'; -import { PoweredByBadge } from 'src/components/wallet'; import { DashboardAnchor } from 'src/constants/suite/anchors'; -import { useDispatch, useSelector } from 'src/hooks/suite'; +import { useSelector } from 'src/hooks/suite'; import { useAnchor } from 'src/hooks/suite/useAnchor'; import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; -import { selectRouteName } from 'src/reducers/suite/routerReducer'; -import { StakingDashboardAccountRow } from './StakingDashboardAccountRow'; -import { StakingDashboardActivateRow } from './StakingDashboardActivateRow'; - -const getBadgeState = ( - isStakingActive: boolean, - accounts: Account[], -): { intent: BadgeIntent; label: TranslationKey } => { - if (!isStakingActive) { - return { - intent: 'neutral', - label: 'TR_STAKING_DASHBOARD_NOT_ACTIVE', - }; - } - - if (accounts.some(account => isCardanoStakedWithFiveBinaries(account))) { - return { - intent: 'warning', - label: 'TR_STAKING_DASHBOARD_OUTDATED', - }; - } - - return { - intent: 'brand', - label: 'TR_STAKING_DASHBOARD_ACTIVE', - }; -}; +import { EarnStakingAccountRow } from './EarnStakingAccountRow'; +import { EarnStakingActivateRow } from './EarnStakingActivateRow'; +import { EarnDashboardSection } from '../common/EarnDashboardSection'; +import { EarnDashboardTableHeader } from '../common/EarnDashboardTableHeader'; +import { getEarnDashboardBadgeState } from '../utils/earnDashboardBadgeUtils'; const useCryptoCurrentRate = (symbol: NetworkSymbol) => { const baseCurrency = useSelector(selectBaseCurrency); @@ -63,18 +37,7 @@ const useCryptoCurrentRate = (symbol: NetworkSymbol) => { return currentRate?.rate; }; -interface StakingDashboardProps { - collapsible?: boolean; -} - -export const StakingDashboard = ({ collapsible = true }: StakingDashboardProps) => { - const dispatch = useDispatch(); - - const routeName = useSelector(selectRouteName); - const isOnEarnPage = routeName === 'suite-earn'; - - const collapsed = useSelector(state => state.suite.stakingDashboardCollapsed); - +export const EarnStakingTable = () => { const { anchorRef, shouldHighlight } = useAnchor(DashboardAnchor.Staking); const ethCurrentRate = useCryptoCurrentRate('eth'); @@ -185,82 +148,55 @@ export const StakingDashboard = ({ collapsible = true }: StakingDashboardProps) const ethNotActivated = deviceSupportedNetworkSymbols.includes('eth') && - !stakingAccounts.find(account => account.symbol === 'eth'); + !stakingAccounts.some(account => account.symbol === 'eth') && + !isEthStakingDisabled; const solNotActivated = deviceSupportedNetworkSymbols.includes('sol') && - !stakingAccounts.find(account => account.symbol === 'sol'); + !stakingAccounts.some(account => account.symbol === 'sol') && + !isSolStakingDisabled; const adaNotActivated = deviceSupportedNetworkSymbols.includes('ada') && - !stakingAccounts.find(account => account.symbol === 'ada'); + !stakingAccounts.some(account => account.symbol === 'ada') && + !isAdaStakingDisabled; const stakingAccountsNotActivated = ethNotActivated && solNotActivated && adaNotActivated; - const onCollapseChange = (collapsed: boolean) => { - if (!collapsible) return; - dispatch(setStakingDashboardCollapsed(collapsed)); - }; - - const badge = getBadgeState(isStakingActive, stakingAccounts); + const badge = getEarnDashboardBadgeState({ + isSectionActive: isStakingActive, + isSectionOutdated: stakingAccounts.some(account => + isCardanoStakedWithFiveBinaries(account), + ), + activeLabelId: 'TR_EARN_DASHBOARD_ACTIVE', + notActiveLabelId: 'TR_EARN_DASHBOARD_NOT_ACTIVE', + outdatedLabelId: 'TR_EARN_STAKING_DASHBOARD_OUTDATED', + }); return ( - - - - - - - } - subheading={} - collapsible={collapsible} - defaultCollapsed={collapsible ? collapsed : false} - onCollapseChange={onCollapseChange} - actions={isOnEarnPage ? : undefined} - ref={anchorRef} + - - - - - - - - - - {!stakingAccountsNotActivated && ( - - )} - - - {!stakingAccountsNotActivated && ( - - )} - - - - + {sortedAccounts.map(account => ( - + ))} - {ethNotActivated && !isEthStakingDisabled && ( - - )} - {solNotActivated && !isSolStakingDisabled && ( - - )} - {adaNotActivated && !isAdaStakingDisabled && ( - - )} + {ethNotActivated && } + {adaNotActivated && } + {solNotActivated && }
-
+
); }; diff --git a/packages/suite/src/components/earn/EarnDashboard/utils/earnDashboardBadgeUtils.ts b/packages/suite/src/components/earn/EarnDashboard/utils/earnDashboardBadgeUtils.ts new file mode 100644 index 0000000000..f213b9389f --- /dev/null +++ b/packages/suite/src/components/earn/EarnDashboard/utils/earnDashboardBadgeUtils.ts @@ -0,0 +1,42 @@ +import { TranslationKey } from '@suite/intl'; +import { BadgeIntent } from '@trezor/components'; + +type EarnDashboardBadgeState = { + intent: BadgeIntent; + labelId: TranslationKey; +}; + +type GetEarnDashboardBadgeStateParams = { + isSectionActive: boolean; + activeLabelId: TranslationKey; + notActiveLabelId: TranslationKey; + isSectionOutdated?: boolean; + outdatedLabelId?: TranslationKey; +}; + +export const getEarnDashboardBadgeState = ({ + isSectionActive, + activeLabelId, + notActiveLabelId, + isSectionOutdated, + outdatedLabelId, +}: GetEarnDashboardBadgeStateParams): EarnDashboardBadgeState => { + if (!isSectionActive) { + return { + intent: 'neutral', + labelId: notActiveLabelId, + }; + } + + if (isSectionOutdated && outdatedLabelId) { + return { + intent: 'warning', + labelId: outdatedLabelId, + }; + } + + return { + intent: 'brand', + labelId: activeLabelId, + }; +}; diff --git a/packages/suite/src/components/earn/EarnDashboard/yield/EarnYieldTable.tsx b/packages/suite/src/components/earn/EarnDashboard/yield/EarnYieldTable.tsx new file mode 100644 index 0000000000..c0d544630d --- /dev/null +++ b/packages/suite/src/components/earn/EarnDashboard/yield/EarnYieldTable.tsx @@ -0,0 +1,105 @@ +import { Translation } from '@suite/intl'; +import { selectVisibleDeviceAccounts } from '@suite-common/wallet-core'; +import { Button, Card, Paragraph, Row, Table } from '@trezor/components'; +import { BigNumber } from '@trezor/utils'; + +import { useSelector } from 'src/hooks/suite'; + +import { EarnAccountCell } from '../common/EarnAccountCell'; +import { EarnDashboardSection } from '../common/EarnDashboardSection'; +import { EarnDashboardTableHeader } from '../common/EarnDashboardTableHeader'; +import { getEarnDashboardBadgeState } from '../utils/earnDashboardBadgeUtils'; + +export const EarnYieldTable = () => { + const visibleAccounts = useSelector(selectVisibleDeviceAccounts); + const ethereumAccounts = visibleAccounts.filter(account => account.symbol === 'eth'); + const isYieldActive = ethereumAccounts.some(account => + new BigNumber(account.formattedBalance).gt(0), + ); + + const badge = getEarnDashboardBadgeState({ + isSectionActive: isYieldActive, + activeLabelId: 'TR_EARN_DASHBOARD_ACTIVE', + notActiveLabelId: 'TR_EARN_DASHBOARD_NOT_ACTIVE', + }); + + return ( + + + + + + + {ethereumAccounts.length === 0 ? ( + + + + + + + + ) : ( + ethereumAccounts.map(account => { + const hasBalance = new BigNumber(account.formattedBalance).gt(0); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + {hasBalance ? ( + <> + + + + ) : ( + + )} + + + + ); + }) + )} + +
+
+
+ ); +}; diff --git a/packages/suite/src/components/earn/index.ts b/packages/suite/src/components/earn/index.ts index dd36331c31..0854dee452 100644 --- a/packages/suite/src/components/earn/index.ts +++ b/packages/suite/src/components/earn/index.ts @@ -6,9 +6,12 @@ export { EarnProviderConsentModal } from './modals/EarnProviderConsent/EarnProvi export { StakingEarnProviderConsentModal } from './modals/EarnProviderConsent/StakingEarnProviderConsentModal'; export { YieldEarnProviderConsentModal } from './modals/EarnProviderConsent/YieldEarnProviderConsentModal'; export { UpdateEarnProviderConsentModal } from './modals/EarnProviderConsent/UpdateEarnProviderConsentModal'; +export { EarnDashboard } from './EarnDashboard/EarnDashboard'; export { EarnSupplyingInfo } from './modals/EarnInANutshell/components/EarnSupplyingInfo'; export { EarnWithdrawingInfo } from './modals/EarnInANutshell/components/EarnWithdrawingInfo'; export { VotingDelegations } from './VotingDelegations/VotingDelegations'; export { VotingDelegationsOptions } from './VotingDelegations/VotingDelegationsOptions'; + +export { PoweredByBadge } from './providers/PoweredByBadge'; diff --git a/packages/suite/src/components/wallet/PoweredByBadge.tsx b/packages/suite/src/components/earn/providers/PoweredByBadge.tsx similarity index 58% rename from packages/suite/src/components/wallet/PoweredByBadge.tsx rename to packages/suite/src/components/earn/providers/PoweredByBadge.tsx index 8025948a69..d892c2c2b7 100644 --- a/packages/suite/src/components/wallet/PoweredByBadge.tsx +++ b/packages/suite/src/components/earn/providers/PoweredByBadge.tsx @@ -1,21 +1,20 @@ import styled from 'styled-components'; import { Translation } from '@suite/intl'; -import { Image, ImageType, Row, Text } from '@trezor/components'; +import { Image, Row, Text } from '@trezor/components'; -const PROVIDERS = { - everstake: { - logo: 'EVERSTAKE_LOGO', - }, -} as const satisfies Record; +import { + type EarnProviderId, + earnProviderMetadata, +} from 'src/components/earn/providers/providerMetadata'; const ImageWrapper = styled.div` filter: ${({ theme }) => (theme.variant === 'dark' ? 'invert(1)' : 'none')}; `; -interface PoweredByBadgeProps { - provider: keyof typeof PROVIDERS; -} +type PoweredByBadgeProps = { + provider: EarnProviderId; +}; export function PoweredByBadge({ provider }: PoweredByBadgeProps) { return ( @@ -24,7 +23,7 @@ export function PoweredByBadge({ provider }: PoweredByBadgeProps) { - +
); diff --git a/packages/suite/src/components/earn/providers/providerMetadata.ts b/packages/suite/src/components/earn/providers/providerMetadata.ts new file mode 100644 index 0000000000..697f37b233 --- /dev/null +++ b/packages/suite/src/components/earn/providers/providerMetadata.ts @@ -0,0 +1,19 @@ +import { ImageType } from '@trezor/components'; + +type ProviderMetadata = { + name: string; + logo: ImageType; +}; + +export const earnProviderMetadata = { + everstake: { + name: 'Everstake', + logo: 'EVERSTAKE_LOGO', + }, + morpho: { + name: 'Morpho', + logo: 'MORPHO_LOGO', + }, +} as const satisfies Record; + +export type EarnProviderId = keyof typeof earnProviderMetadata; diff --git a/packages/suite/src/components/wallet/index.tsx b/packages/suite/src/components/wallet/index.tsx index 41613b5630..3221790525 100644 --- a/packages/suite/src/components/wallet/index.tsx +++ b/packages/suite/src/components/wallet/index.tsx @@ -3,7 +3,6 @@ import { CoinjoinAccountDiscoveryProgress } from './CoinjoinAccountDiscoveryProg import { DiscoveryProgress } from './DiscoveryProgress'; import { InputError } from './InputError'; import { Pagination } from './Pagination'; -import { PoweredByBadge } from './PoweredByBadge'; import { TransactionTimestamp } from './TransactionTimestamp'; import { UtxoAnonymity } from './UtxoAnonymity'; import { WalletLayout } from './WalletLayout/WalletLayout'; @@ -19,5 +18,4 @@ export { Pagination, TransactionTimestamp, CoinjoinAccountDiscoveryProgress, - PoweredByBadge, }; diff --git a/packages/suite/src/middlewares/wallet/storageMiddleware.ts b/packages/suite/src/middlewares/wallet/storageMiddleware.ts index 4f51306cdf..2807a9e3c6 100644 --- a/packages/suite/src/middlewares/wallet/storageMiddleware.ts +++ b/packages/suite/src/middlewares/wallet/storageMiddleware.ts @@ -315,7 +315,6 @@ const storageMiddleware = (api: MiddlewareAPI) => { case SUITE.SET_ADDRESS_DISPLAY_TYPE: case SUITE.SET_AUTODETECT: case SUITE.SET_SIDEBAR_WIDTH: - case SUITE.SET_STAKING_DASHBOARD_COLLAPSED: case SUITE.TOGGLE_DEVICE_AUTHENTICITY_CHECK: case SUITE.TOGGLE_FIRMWARE_REVISION_CHECK: case SUITE.TOGGLE_FIRMWARE_HASH_CHECK: diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts index eb06f2a3b3..ee25039e6a 100644 --- a/packages/suite/src/reducers/suite/suiteReducer.ts +++ b/packages/suite/src/reducers/suite/suiteReducer.ts @@ -129,7 +129,6 @@ export interface SuiteState { recentlyConnectedDeviceRef: string | null; // TODO use type DeviceRef from suite-types; currently WIP in https://github.com/trezor/trezor-suite/pull/20955 recentlyDisconnectedDevice: string | null; seenDisconnectNotificationForDeviceIds: string[]; - stakingDashboardCollapsed: boolean; } const initialState: SuiteState = { @@ -212,7 +211,6 @@ const initialState: SuiteState = { recentlyConnectedDeviceRef: null, recentlyDisconnectedDevice: null, seenDisconnectNotificationForDeviceIds: [], - stakingDashboardCollapsed: false, }; export const suiteInitialState = initialState; @@ -249,10 +247,6 @@ const suiteReducer = (state: SuiteState = initialState, action: Action): SuiteSt ...draft.settings, ...action.payload.suiteSettings?.settings, }; - if (typeof action.payload.suiteSettings?.stakingDashboardCollapsed === 'boolean') { - draft.stakingDashboardCollapsed = - action.payload.suiteSettings.stakingDashboardCollapsed; - } break; case STORAGE.ERROR: draft.lifecycle = { status: 'db-error', error: action.payload }; @@ -327,10 +321,6 @@ const suiteReducer = (state: SuiteState = initialState, action: Action): SuiteSt draft.settings.theme.variant = action.variant; break; - case SUITE.SET_STAKING_DASHBOARD_COLLAPSED: - draft.stakingDashboardCollapsed = action.isCollapsed; - break; - case SUITE.SET_SEND_FORM_PREFILL: draft.prefillFields.sendForm = action.payload.contractAddress; break; diff --git a/packages/suite/src/storage/definitions.ts b/packages/suite/src/storage/definitions.ts index 8660137932..e31842d1fe 100644 --- a/packages/suite/src/storage/definitions.ts +++ b/packages/suite/src/storage/definitions.ts @@ -70,7 +70,6 @@ export interface SuiteDBSchema extends DBSchema { flags: SuiteState['flags']; evmSettings: SuiteState['evmSettings']; seenDisconnectNotificationForDeviceIds: SuiteState['seenDisconnectNotificationForDeviceIds']; - stakingDashboardCollapsed: SuiteState['stakingDashboardCollapsed']; }; }; historicRates: { diff --git a/packages/suite/src/views/dashboard/index.tsx b/packages/suite/src/views/dashboard/index.tsx index 2069548127..04d64dd234 100644 --- a/packages/suite/src/views/dashboard/index.tsx +++ b/packages/suite/src/views/dashboard/index.tsx @@ -4,6 +4,7 @@ import { Context } from '@suite-common/message-system'; import { Column } from '@trezor/components'; import { spacings, spacingsPx } from '@trezor/theme'; +import { EarnDashboard } from 'src/components/earn'; import { PageHeader } from 'src/components/suite/layouts/SuiteLayout'; import { ContextMessage } from 'src/components/wallet/WalletLayout/AccountBanners/ContextMessage'; import { useLayout } from 'src/hooks/suite'; @@ -12,7 +13,6 @@ import { AssetsView } from './AssetsView/AssetsView'; import { DashboardFooter } from './DashboardFooter'; import { DashboardPromoBanner } from './DashboardPromoBanner/DashboardPromoBanner'; import { PortfolioCard } from './PortfolioCard/PortfolioCard'; -import { StakingDashboard } from './StakingDashboard/StakingDashboard'; import { useNotificationForDisconnectedDevice } from './useNotificationForDisconnectedDevice'; const Container = styled.div` @@ -33,7 +33,7 @@ export const Dashboard = () => { - + ); diff --git a/packages/suite/src/views/earn/index.tsx b/packages/suite/src/views/earn/index.tsx index 5ef6fd96cf..0b1038d082 100644 --- a/packages/suite/src/views/earn/index.tsx +++ b/packages/suite/src/views/earn/index.tsx @@ -1,10 +1,9 @@ +import { EarnDashboard } from 'src/components/earn'; import { PageHeader } from 'src/components/suite/layouts/SuiteLayout'; import { useLayout } from 'src/hooks/suite'; -import { StakingDashboard } from '../dashboard/StakingDashboard/StakingDashboard'; - export const Earn = () => { useLayout('Earn', ); - return ; + return ; }; diff --git a/packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EverstakeFooter.tsx b/packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EverstakeFooter.tsx index 58b4f6770f..bd2acbc316 100644 --- a/packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EverstakeFooter.tsx +++ b/packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EverstakeFooter.tsx @@ -9,8 +9,8 @@ import { HELP_CENTER_SOL_STAKING, } from '@trezor/urls'; +import { PoweredByBadge } from 'src/components/earn'; import { LearnMoreButton } from 'src/components/suite/LearnMoreButton'; -import { PoweredByBadge } from 'src/components/wallet'; import { useSelector } from 'src/hooks/suite'; import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; diff --git a/suite/intl/src/messages.ts b/suite/intl/src/messages.ts index 016aca90da..c1f31a8bc9 100644 --- a/suite/intl/src/messages.ts +++ b/suite/intl/src/messages.ts @@ -8896,25 +8896,45 @@ export const messages = defineMessages({ id: 'TR_TO', defaultMessage: 'To', }, - TR_STAKING_DASHBOARD_TITLE: { - id: 'TR_STAKING_DASHBOARD_TITLE', + TR_EARN_STAKING_DASHBOARD_TITLE: { + id: 'TR_EARN_STAKING_DASHBOARD_TITLE', defaultMessage: 'Staking', }, - TR_STAKING_DASHBOARD_TEXT: { - id: 'TR_STAKING_DASHBOARD_TEXT', + TR_EARN_STAKING_DASHBOARD_TEXT: { + id: 'TR_EARN_STAKING_DASHBOARD_TEXT', defaultMessage: 'Grow your crypto by locking it to help secure the network—and earn rewards in return.', }, - TR_STAKING_DASHBOARD_ACTIVE: { - id: 'TR_STAKING_DASHBOARD_ACTIVE', + TR_EARN_YIELD_DASHBOARD_TITLE: { + id: 'TR_EARN_YIELD_DASHBOARD_TITLE', + defaultMessage: 'Stablecoin yield', + }, + TR_EARN_YIELD_DASHBOARD_TEXT: { + id: 'TR_EARN_YIELD_DASHBOARD_TEXT', + defaultMessage: 'Put your stablecoins to work and earn rewards.', + }, + TR_EARN_YIELD_DASHBOARD_SUPPLY_MORE: { + id: 'TR_EARN_YIELD_DASHBOARD_SUPPLY_MORE', + defaultMessage: 'Supply more', + }, + TR_EARN_YIELD_DASHBOARD_WITHDRAW: { + id: 'TR_EARN_YIELD_DASHBOARD_WITHDRAW', + defaultMessage: 'Withdraw', + }, + TR_EARN_YIELD_DASHBOARD_SUPPLY_NOW: { + id: 'TR_EARN_YIELD_DASHBOARD_SUPPLY_NOW', + defaultMessage: 'Supply now', + }, + TR_EARN_DASHBOARD_ACTIVE: { + id: 'TR_EARN_DASHBOARD_ACTIVE', defaultMessage: 'Active', }, - TR_STAKING_DASHBOARD_NOT_ACTIVE: { - id: 'TR_STAKING_DASHBOARD_NOT_ACTIVE', + TR_EARN_DASHBOARD_NOT_ACTIVE: { + id: 'TR_EARN_DASHBOARD_NOT_ACTIVE', defaultMessage: 'Inactive', }, - TR_STAKING_DASHBOARD_OUTDATED: { - id: 'TR_STAKING_DASHBOARD_OUTDATED', + TR_EARN_STAKING_DASHBOARD_OUTDATED: { + id: 'TR_EARN_STAKING_DASHBOARD_OUTDATED', defaultMessage: 'Outdated provider', }, TR_STAKING_MODAL_OUTDATED: { @@ -8930,52 +8950,52 @@ export const messages = defineMessages({ id: 'TR_STAKING_MODAL_OUTDATED_BUTTON', defaultMessage: 'Update provider', }, - TR_STAKING_DASHBOARD_TABLE_ACCOUNT_BALANCE: { - id: 'TR_STAKING_DASHBOARD_TABLE_ACCOUNT_BALANCE', - defaultMessage: 'Account', + TR_EARN_DASHBOARD_TABLE_ACCOUNT_BALANCE: { + id: 'TR_EARN_DASHBOARD_TABLE_ACCOUNT_BALANCE', + defaultMessage: 'Account & balance', }, - TR_STAKING_DASHBOARD_TABLE_APY: { - id: 'TR_STAKING_DASHBOARD_TABLE_APY', + TR_EARN_DASHBOARD_TABLE_APY: { + id: 'TR_EARN_DASHBOARD_TABLE_APY', defaultMessage: 'APY', }, - TR_STAKING_DASHBOARD_TABLE_YEARLY_REWARDS: { - id: 'TR_STAKING_DASHBOARD_TABLE_YEARLY_REWARDS', + TR_EARN_DASHBOARD_TABLE_YEARLY_REWARDS: { + id: 'TR_EARN_DASHBOARD_TABLE_YEARLY_REWARDS', defaultMessage: 'Your yearly rewards', }, - TR_STAKING_DASHBOARD_TABLE_POTENTIAL_REWARDS: { - id: 'TR_STAKING_DASHBOARD_TABLE_POTENTIAL_REWARDS', + TR_EARN_DASHBOARD_TABLE_POTENTIAL_REWARDS: { + id: 'TR_EARN_DASHBOARD_TABLE_POTENTIAL_REWARDS', defaultMessage: 'Potential rewards', }, - TR_STAKING_DASHBOARD_STAKE_NOW: { - id: 'TR_STAKING_DASHBOARD_STAKE_NOW', + TR_EARN_STAKING_DASHBOARD_STAKE_NOW: { + id: 'TR_EARN_STAKING_DASHBOARD_STAKE_NOW', defaultMessage: 'Stake now', }, - TR_STAKING_DASHBOARD_STAKE_MORE: { - id: 'TR_STAKING_DASHBOARD_STAKE_MORE', + TR_EARN_STAKING_DASHBOARD_STAKE_MORE: { + id: 'TR_EARN_STAKING_DASHBOARD_STAKE_MORE', defaultMessage: 'Stake more', }, - TR_STAKING_DASHBOARD_ACTIVATE: { - id: 'TR_STAKING_DASHBOARD_ACTIVATE', + TR_EARN_STAKING_DASHBOARD_ACTIVATE: { + id: 'TR_EARN_STAKING_DASHBOARD_ACTIVATE', defaultMessage: 'Activate {networkName}', }, - TR_STAKING_DASHBOARD_MINIMUM_STAKE: { - id: 'TR_STAKING_DASHBOARD_MINIMUM_STAKE', + TR_EARN_STAKING_DASHBOARD_MINIMUM_STAKE: { + id: 'TR_EARN_STAKING_DASHBOARD_MINIMUM_STAKE', defaultMessage: 'Minimum {amount} {displaySymbol} required to stake', }, - TR_STAKING_DASHBOARD_MAXIMUM_STAKE: { - id: 'TR_STAKING_DASHBOARD_MAXIMUM_STAKE', + TR_EARN_STAKING_DASHBOARD_MAXIMUM_STAKE: { + id: 'TR_EARN_STAKING_DASHBOARD_MAXIMUM_STAKE', defaultMessage: 'Maximum staked', }, - TR_STAKING_DASHBOARD_IF_YOU_ADD: { - id: 'TR_STAKING_DASHBOARD_IF_YOU_ADD', + TR_EARN_STAKING_DASHBOARD_IF_YOU_ADD: { + id: 'TR_EARN_STAKING_DASHBOARD_IF_YOU_ADD', defaultMessage: 'if you add {amount} {displaySymbol}', }, - TR_STAKING_DASHBOARD_STAKED: { - id: 'TR_STAKING_DASHBOARD_STAKED', + TR_EARN_STAKING_DASHBOARD_STAKED: { + id: 'TR_EARN_STAKING_DASHBOARD_STAKED', defaultMessage: '{amount} {displaySymbol} staked', }, - TR_STAKING_DASHBOARD_OUTDATED_PROVIDER: { - id: 'TR_STAKING_DASHBOARD_OUTDATED_PROVIDER', + TR_EARN_STAKING_DASHBOARD_OUTDATED_PROVIDER: { + id: 'TR_EARN_STAKING_DASHBOARD_OUTDATED_PROVIDER', defaultMessage: 'Update to Everstake and earn ~{apy}% APY', }, TR_STAKING_BANNER_DETAIL_TITLE: { @@ -9205,8 +9225,8 @@ export const messages = defineMessages({ id: 'TR_STAKE_N_A', defaultMessage: 'N/A', }, - TR_STAKE_APY_REQUIRED: { - id: 'TR_STAKE_APY_REQUIRED', + TR_EARN_APY_REQUIRED: { + id: 'TR_EARN_APY_REQUIRED', defaultMessage: 'APY required to calculate rewards', }, TR_STAKE_APY_DESC: {