From 12ad0b37fd61092843cc832ac9015b6be51b62c2 Mon Sep 17 00:00:00 2001 From: Daniel Dimitrov Date: Tue, 17 Sep 2024 11:12:20 +0200 Subject: [PATCH] feat: add stake button on assets page fix: add area-label to stake button --- public/images/common/stake.svg | 2 +- src/components/balances/AssetsTable/index.tsx | 10 +++- .../stake/components/StakeButton/index.tsx | 58 +++++++++++++++++++ .../stake/components/StakePage/index.tsx | 5 +- .../stake/components/StakingWidget/index.tsx | 31 ++-------- src/features/stake/constants.ts | 10 ++++ .../stake/hooks/useGetStakeWidgetUrl.ts | 24 ++++++++ .../stake/hooks/useIsSwapFeatureEnabled.ts | 11 ++++ src/services/analytics/events/stake.ts | 14 +++++ 9 files changed, 137 insertions(+), 28 deletions(-) create mode 100644 src/features/stake/components/StakeButton/index.tsx create mode 100644 src/features/stake/hooks/useGetStakeWidgetUrl.ts create mode 100644 src/features/stake/hooks/useIsSwapFeatureEnabled.ts create mode 100644 src/services/analytics/events/stake.ts diff --git a/public/images/common/stake.svg b/public/images/common/stake.svg index b0a4b399df..41469d1e83 100644 --- a/public/images/common/stake.svg +++ b/public/images/common/stake.svg @@ -1,4 +1,4 @@ - + diff --git a/src/components/balances/AssetsTable/index.tsx b/src/components/balances/AssetsTable/index.tsx index c04d795040..077bfed573 100644 --- a/src/components/balances/AssetsTable/index.tsx +++ b/src/components/balances/AssetsTable/index.tsx @@ -1,6 +1,6 @@ import CheckBalance from '@/features/counterfactual/CheckBalance' import { type ReactElement } from 'react' -import { Tooltip, Typography, SvgIcon, IconButton, Box, Checkbox, Skeleton } from '@mui/material' +import { Box, IconButton, Checkbox, Skeleton, SvgIcon, Tooltip, Typography } from '@mui/material' import type { TokenInfo } from '@safe-global/safe-gateway-typescript-sdk' import { TokenType } from '@safe-global/safe-gateway-typescript-sdk' import css from './styles.module.css' @@ -21,6 +21,9 @@ import SwapButton from '@/features/swap/components/SwapButton' import { SWAP_LABELS } from '@/services/analytics/events/swaps' import SendButton from './SendButton' import useIsSwapFeatureEnabled from '@/features/swap/hooks/useIsSwapFeatureEnabled' +import useIsStakingFeatureEnabled from '@/features/stake/hooks/useIsSwapFeatureEnabled' +import { STAKE_LABELS } from '@/services/analytics/events/stake' +import StakeButton from '@/features/stake/components/StakeButton' const skeletonCells: EnhancedTableProps['rows'][0]['cells'] = { asset: { @@ -97,6 +100,7 @@ const AssetsTable = ({ }): ReactElement => { const { balances, loading } = useBalances() const isSwapFeatureEnabled = useIsSwapFeatureEnabled() + const isStakingFeatureEnabled = useIsStakingFeatureEnabled() const { isAssetSelected, toggleAsset, hidingAsset, hideAsset, cancel, deselectAll, saveChanges } = useHideAssets(() => setShowHiddenAssets(false), @@ -130,6 +134,10 @@ const AssetsTable = ({ {item.tokenInfo.name} + {isStakingFeatureEnabled && item.tokenInfo.type === TokenType.NATIVE_TOKEN && ( + + )} + {!isNative && } ), diff --git a/src/features/stake/components/StakeButton/index.tsx b/src/features/stake/components/StakeButton/index.tsx new file mode 100644 index 0000000000..efe0b38228 --- /dev/null +++ b/src/features/stake/components/StakeButton/index.tsx @@ -0,0 +1,58 @@ +import CheckWallet from '@/components/common/CheckWallet' +import Track from '@/components/common/Track' +import { AppRoutes } from '@/config/routes' +import useSpendingLimit from '@/hooks/useSpendingLimit' +import { Button } from '@mui/material' +import type { TokenInfo } from '@safe-global/safe-gateway-typescript-sdk' +import { TokenType } from '@safe-global/safe-gateway-typescript-sdk' +import { useRouter } from 'next/router' +import type { ReactElement } from 'react' +import StakeIcon from '@/public/images/common/stake.svg' +import type { STAKE_LABELS } from '@/services/analytics/events/stake' +import { STAKE_EVENTS } from '@/services/analytics/events/stake' +import { useCurrentChain } from '@/hooks/useChains' + +const StakeButton = ({ + tokenInfo, + trackingLabel, +}: { + tokenInfo: TokenInfo + trackingLabel: STAKE_LABELS +}): ReactElement => { + const spendingLimit = useSpendingLimit(tokenInfo) + const chain = useCurrentChain() + const router = useRouter() + + return ( + + {(isOk) => ( + + + + )} + + ) +} + +export default StakeButton diff --git a/src/features/stake/components/StakePage/index.tsx b/src/features/stake/components/StakePage/index.tsx index 7ab3382e1e..060cc84b6a 100644 --- a/src/features/stake/components/StakePage/index.tsx +++ b/src/features/stake/components/StakePage/index.tsx @@ -3,14 +3,17 @@ import Disclaimer from '@/components/common/Disclaimer' import WidgetDisclaimer from '@/components/common/WidgetDisclaimer' import useStakeConsent from '@/features/stake/useStakeConsent' import StakingWidget from '../StakingWidget' +import { useRouter } from 'next/router' const StakePage = () => { const { isConsentAccepted, onAccept } = useStakeConsent() + const router = useRouter() + const { asset } = router.query return ( <> {isConsentAccepted === undefined ? null : isConsentAccepted ? ( - + ) : ( { - const isDarkMode = useDarkMode() - let url = widgetAppData.url - const currentChainId = useChainId() - const { configs } = useChains() - const testChains = useMemo(() => configs.filter((chain) => chain.isTestnet), [configs]) - - // if currentChainId is in testChains, then set the url to the testnet version - if (testChains.some((chain) => chain.chainId === currentChainId)) { - url = WIDGET_TESTNET_URL - } +const StakingWidget = ({ asset }: { asset?: string }) => { + const url = useGetStakeWidgetUrl(asset) const appData = useMemo( () => ({ ...getEmptySafeApp(), ...widgetAppData, - url: url + `?theme=${isDarkMode ? 'dark' : 'light'}`, + url, }), - [isDarkMode, url], + [url], ) return ( diff --git a/src/features/stake/constants.ts b/src/features/stake/constants.ts index 59b8a35621..cc4925f5f9 100644 --- a/src/features/stake/constants.ts +++ b/src/features/stake/constants.ts @@ -1 +1,11 @@ export const STAKE_TITLE = 'Stake' + +export const WIDGET_PRODUCTION_URL = 'https://safe.widget.kiln.fi/earn' +export const WIDGET_TESTNET_URL = 'https://safe.widget.testnet.kiln.fi/earn' + +export const widgetAppData = { + url: WIDGET_PRODUCTION_URL, + name: STAKE_TITLE, + iconUrl: '/images/common/stake.svg', + chainIds: ['17000', '11155111', '1', '42161', '137', '56', '8453', '10'], +} diff --git a/src/features/stake/hooks/useGetStakeWidgetUrl.ts b/src/features/stake/hooks/useGetStakeWidgetUrl.ts new file mode 100644 index 0000000000..f14c4ef1b1 --- /dev/null +++ b/src/features/stake/hooks/useGetStakeWidgetUrl.ts @@ -0,0 +1,24 @@ +import { useDarkMode } from '@/hooks/useDarkMode' +import useChainId from '@/hooks/useChainId' +import useChains from '@/hooks/useChains' +import { useMemo } from 'react' +import { WIDGET_PRODUCTION_URL, WIDGET_TESTNET_URL } from '@/features/stake/constants' + +export const useGetStakeWidgetUrl = (asset?: string) => { + let url = WIDGET_PRODUCTION_URL + const isDarkMode = useDarkMode() + const currentChainId = useChainId() + const { configs } = useChains() + const testChains = useMemo(() => configs.filter((chain) => chain.isTestnet), [configs]) + if (testChains.some((chain) => chain.chainId === currentChainId)) { + url = WIDGET_TESTNET_URL + } + const params = new URLSearchParams() + params.append('theme', isDarkMode ? 'dark' : 'light') + + if (asset) { + params.append('asset', asset) + } + + return url + '?' + params.toString() +} diff --git a/src/features/stake/hooks/useIsSwapFeatureEnabled.ts b/src/features/stake/hooks/useIsSwapFeatureEnabled.ts new file mode 100644 index 0000000000..964072036a --- /dev/null +++ b/src/features/stake/hooks/useIsSwapFeatureEnabled.ts @@ -0,0 +1,11 @@ +import { GeoblockingContext } from '@/components/common/GeoblockingProvider' +import { useHasFeature } from '@/hooks/useChains' +import { FEATURES } from '@/utils/chains' +import { useContext } from 'react' + +const useIsStakingFeatureEnabled = () => { + const isBlockedCountry = useContext(GeoblockingContext) + return useHasFeature(FEATURES.STAKING) && !isBlockedCountry +} + +export default useIsStakingFeatureEnabled diff --git a/src/services/analytics/events/stake.ts b/src/services/analytics/events/stake.ts new file mode 100644 index 0000000000..6754939484 --- /dev/null +++ b/src/services/analytics/events/stake.ts @@ -0,0 +1,14 @@ +const STAKE_CATEGORY = 'stake' + +export const STAKE_EVENTS = { + OPEN_STAKE: { + action: 'Open stake', + category: STAKE_CATEGORY, + }, +} + +export enum STAKE_LABELS { + dashboard = 'dashboard', + sidebar = 'sidebar', + asset = 'asset', +}