diff --git a/src/hooks/useRouteAssetId/useRouteAssetId.ts b/src/hooks/useRouteAssetId/useRouteAssetId.ts index 75a9a546947..6de96bdd64d 100644 --- a/src/hooks/useRouteAssetId/useRouteAssetId.ts +++ b/src/hooks/useRouteAssetId/useRouteAssetId.ts @@ -1,6 +1,5 @@ import type { AccountId, AssetId, ChainNamespace, ChainReference } from '@shapeshiftoss/caip' import { toChainId } from '@shapeshiftoss/caip' -import { getFoxPageRouteAssetId } from 'plugins/foxPage/utils/getFoxPageRouteAssetId' import { useMemo } from 'react' import { matchPath, useLocation } from 'react-router' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' @@ -65,9 +64,8 @@ export const useRouteAssetId = () => { const assetId = useMemo(() => { const routeAssetId = getRouteAssetId(location.pathname) - const foxPageRouteAssetId = getFoxPageRouteAssetId(location.pathname) - return decodeURIComponent(routeAssetId ?? foxPageRouteAssetId) + return decodeURIComponent(routeAssetId ?? '') }, [location.pathname]) return assetId diff --git a/src/plugins/activePlugins.ts b/src/plugins/activePlugins.ts index 16dbae9b245..41db6fa3932 100644 --- a/src/plugins/activePlugins.ts +++ b/src/plugins/activePlugins.ts @@ -8,7 +8,6 @@ import bnbsmartchain from 'plugins/bnbsmartchain' import cosmos from 'plugins/cosmos' import dogecoin from 'plugins/dogecoin' import ethereum from 'plugins/ethereum' -import foxPage from 'plugins/foxPage' import gnosis from 'plugins/gnosis' import litecoin from 'plugins/litecoin' import mobile from 'plugins/mobile' @@ -24,7 +23,6 @@ export const activePlugins = [ dogecoin, litecoin, ethereum, - foxPage, polygon, gnosis, avalanche, diff --git a/src/plugins/foxPage/FoxCommon.ts b/src/plugins/foxPage/FoxCommon.ts deleted file mode 100644 index 78487b98a8d..00000000000 --- a/src/plugins/foxPage/FoxCommon.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { DefiType } from 'state/slices/opportunitiesSlice/types' - -import type { TradeOpportunitiesBucket } from './components/TradeOpportunities' - -export const TrimmedDescriptionLength = 191 - -export enum OpportunityTypes { - LiquidityPool = 'liquidityPools', - Farming = 'farming', - BorrowingAndLending = 'borrowingAndLending', -} - -export type ExternalOpportunity = { - name: string | undefined - type?: DefiType - apy?: string | null - link?: string - icons?: string[] | undefined - isLoaded?: boolean - isDisabled?: boolean - contractAddress?: string - provider?: string - highestBalanceAccountAddress?: string -} - -export type OpportunitiesBucket = { - type: OpportunityTypes | DefiType - title: string - opportunities: ExternalOpportunity[] -} - -export const foxTradeOpportunitiesBuckets: TradeOpportunitiesBucket[] = [ - { - title: 'plugins.foxPage.dex', - opportunities: [ - { - link: 'https://app.uniswap.org/#/swap?inputCurrency=ETH&outputCurrency=0xc770eefad204b5180df6a14ee197d99d808ee52d&chain=mainnet', - icon: 'uniswap.png', - }, - { - link: 'https://app.thorswap.finance/swap/ETH.ETH_ETH.FOX-0XC770EEFAD204B5180DF6A14EE197D99D808EE52D', - icon: 'thorswap.png', - }, - ], - }, - { - title: 'plugins.foxPage.centralized', - opportunities: [ - { - link: 'https://www.coinbase.com/price/fox-token', - icon: 'coinbase.png', - }, - ], - }, -] - -export const foxyTradeOpportunitiesBuckets: TradeOpportunitiesBucket[] = [ - { - title: 'plugins.foxPage.dex', - opportunities: [ - { - link: 'https://elasticswap.org/', - icon: 'elasticswap.png', - }, - ], - }, -] diff --git a/src/plugins/foxPage/components/AssetActions.tsx b/src/plugins/foxPage/components/AssetActions.tsx deleted file mode 100644 index b253bcdd143..00000000000 --- a/src/plugins/foxPage/components/AssetActions.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import { ExternalLinkIcon } from '@chakra-ui/icons' -import { - Box, - Button, - Card, - CardBody, - Link, - Skeleton, - SkeletonText, - Stack, - Tab, - TabList, - TabPanel, - TabPanels, - Tabs, - Text as CText, -} from '@chakra-ui/react' -import type { AssetId } from '@shapeshiftoss/caip' -import { foxAssetId } from '@shapeshiftoss/caip' -import { supportsETH } from '@shapeshiftoss/hdwallet-core/dist/wallet' -import isEqual from 'lodash/isEqual' -import qs from 'qs' -import { useCallback, useMemo } from 'react' -import { useTranslate } from 'react-polyglot' -import { useHistory, useLocation } from 'react-router' -import { AssetIcon } from 'components/AssetIcon' -import { MultiHopTrade } from 'components/MultiHopTrade/MultiHopTrade' -import { Text } from 'components/Text/Text' -import { WalletActions } from 'context/WalletProvider/actions' -import { useModal } from 'hooks/useModal/useModal' -import { useWallet } from 'hooks/useWallet/useWallet' -import { foxyAddresses } from 'lib/investor/investor-foxy' -import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton' -import { MixPanelEvents } from 'lib/mixpanel/types' -import { DefiProvider } from 'state/slices/opportunitiesSlice/types' -import { trimWithEndEllipsis } from 'state/slices/portfolioSlice/utils' -import { selectAccountIdsByAssetId, selectAssetById } from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -import { TrimmedDescriptionLength } from '../FoxCommon' - -type FoxTabProps = { - assetId: AssetId -} - -const BuyFoxCoinbaseUrl = 'https://www.coinbase.com/price/fox-token' -const TradeFoxyElasticSwapUrl = `https://elasticswap.org/#/swap` - -const externalLinkIcon = - -export const AssetActions: React.FC = ({ assetId }) => { - const translate = useTranslate() - const location = useLocation() - const history = useHistory() - const asset = useAppSelector(state => selectAssetById(state, assetId)) - if (!asset) throw new Error(`Asset not found for AssetId ${assetId}`) - const { description } = asset || {} - const trimmedDescription = trimWithEndEllipsis(description, TrimmedDescriptionLength) - const isFoxAsset = assetId === foxAssetId - - const filter = useMemo(() => ({ assetId }), [assetId]) - const accountIds = useAppSelector(state => selectAccountIdsByAssetId(state, filter), isEqual) - const accountId = accountIds?.[0] - - const { - state: { isConnected, isDemoWallet, wallet }, - dispatch, - } = useWallet() - const receive = useModal('receive') - - const walletSupportsETH = useMemo(() => Boolean(wallet && supportsETH(wallet)), [wallet]) - - const handleWalletModalOpen = useCallback( - () => dispatch({ type: WalletActions.SET_WALLET_MODAL, payload: true }), - [dispatch], - ) - const handleReceiveClick = useCallback( - () => - !isDemoWallet && isConnected && walletSupportsETH - ? receive.open({ asset, accountId }) - : handleWalletModalOpen(), - [ - accountId, - asset, - handleWalletModalOpen, - isConnected, - isDemoWallet, - receive, - walletSupportsETH, - ], - ) - - const receiveButtonTranslation = useMemo( - () => (!isDemoWallet && walletSupportsETH ? 'plugins.foxPage.receive' : 'common.connectWallet'), - [isDemoWallet, walletSupportsETH], - ) - - const onGetAssetClick = useCallback(() => { - history.push({ - pathname: location.pathname, - search: qs.stringify({ - provider: DefiProvider.ShapeShift, - chainId: asset.chainId, - assetNamespace: 'erc20', - contractAddress: foxyAddresses[0].foxy, - assetReference: foxyAddresses[0].staking, - rewardId: foxyAddresses[0].foxy, - modal: 'overview', - }), - state: { background: location }, - }) - }, [asset.chainId, history, location]) - - const handleCoinbaseButtonClick = useCallback( - () => getMixPanel()?.track(MixPanelEvents.Click, { element: 'Coinbase Button' }), - [], - ) - - return ( - - - - - - {translate('plugins.foxPage.getAsset', { - assetSymbol: asset.symbol, - })} - - - {translate('plugins.foxPage.trade')} - - - - - - - - - - {trimmedDescription} - - - - {!isFoxAsset && ( - - )} - {isFoxAsset && ( - - )} - - - - - - - {isFoxAsset ? : null} - {!isFoxAsset && ( - - - - {translate('plugins.foxPage.tradingUnavailable', { - assetSymbol: asset.symbol, - })} - - - - - )} - - - - - - ) -} diff --git a/src/plugins/foxPage/components/BondProtocolCta.tsx b/src/plugins/foxPage/components/BondProtocolCta.tsx deleted file mode 100644 index 5dbe0b7c6de..00000000000 --- a/src/plugins/foxPage/components/BondProtocolCta.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Button, Card, CardBody, CardHeader, Heading, Link } from '@chakra-ui/react' -import { useCallback } from 'react' -import { useTranslate } from 'react-polyglot' -import { Text } from 'components/Text' -import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton' -import { MixPanelEvents } from 'lib/mixpanel/types' - -export const BondProtocolCta = () => { - const translate = useTranslate() - - const handleClick = useCallback(() => { - getMixPanel()?.track(MixPanelEvents.Click, { element: 'BondProtocol Button' }) - }, []) - return ( - - - - - - - - - - - - ) -} diff --git a/src/plugins/foxPage/components/DappBack.tsx b/src/plugins/foxPage/components/DappBack.tsx deleted file mode 100644 index 5ebe6dcc26b..00000000000 --- a/src/plugins/foxPage/components/DappBack.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Button, Card, CardBody, CardHeader, Heading, Link } from '@chakra-ui/react' -import { useCallback } from 'react' -import { useTranslate } from 'react-polyglot' -import { Text } from 'components/Text' -import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag' -import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton' -import { MixPanelEvents } from 'lib/mixpanel/types' - -export const DappBack = () => { - const translate = useTranslate() - const isFoxBondCTAEnabled = useFeatureFlag('FoxBondCTA') - - const handleClick = useCallback(() => { - getMixPanel()?.track(MixPanelEvents.Click, { element: 'Dappback Button' }) - }, []) - if (!isFoxBondCTAEnabled) return null - return ( - - - - - - - - - - - - ) -} diff --git a/src/plugins/foxPage/components/FoxChart.tsx b/src/plugins/foxPage/components/FoxChart.tsx deleted file mode 100644 index a67d20bdbc9..00000000000 --- a/src/plugins/foxPage/components/FoxChart.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { - Box, - Card, - CardBody, - CardFooter, - Stat, - StatArrow, - StatNumber, - Text, -} from '@chakra-ui/react' -import type { HistoryTimeframe } from '@shapeshiftoss/types' -import { useState } from 'react' -import NumberFormat from 'react-number-format' -import { useTranslate } from 'react-polyglot' -import { TimeControls } from 'components/Graph/TimeControls' -import { PriceChart } from 'components/PriceChart/PriceChart' -import { RawText } from 'components/Text/Text' -import { useLocaleFormatter } from 'hooks/useLocaleFormatter/useLocaleFormatter' -import { useTimeframeChange } from 'hooks/useTimeframeChange/useTimeframeChange' -import { selectChartTimeframe, selectMarketDataById } from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -type FoxChartProps = { - assetId: string -} - -const timeControlsButtonGroupProps = { - display: 'flex', - width: 'full', - justifyContent: 'space-between', -} - -export const FoxChart: React.FC = ({ assetId }) => { - const userChartTimeframe = useAppSelector(selectChartTimeframe) - const [timeframe, setTimeframe] = useState(userChartTimeframe) - const handleTimeframeChange = useTimeframeChange(setTimeframe) - const [percentChange, setPercentChange] = useState(0) - const { - number: { toFiat }, - } = useLocaleFormatter() - const translate = useTranslate() - const marketData = useAppSelector(state => selectMarketDataById(state, assetId)) - const { price } = marketData || {} - const assetPrice = toFiat(price) ?? 0 - - return ( - - - - - {translate('plugins.foxPage.currentPrice')} - - - - - - 0 ? 'green.500' : 'red.500'} - > - 0 ? 'increase' : 'decrease'} /> - {isFinite(percentChange) && {percentChange}%} - - - - - - - - - - ) -} diff --git a/src/plugins/foxPage/components/FoxTab.tsx b/src/plugins/foxPage/components/FoxTab.tsx deleted file mode 100644 index e9a8c8c9b8d..00000000000 --- a/src/plugins/foxPage/components/FoxTab.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import type { ResponsiveValue, TabProps } from '@chakra-ui/react' -import { Card, CardBody, Flex, SkeletonText, Tab, useColorModeValue } from '@chakra-ui/react' -import type { Property } from 'csstype' -import { useMemo } from 'react' -import { Amount } from 'components/Amount/Amount' -import { AssetIcon } from 'components/AssetIcon' - -type FoxTabProps = { - assetIcon: string - assetSymbol: string - fiatAmount: string - cryptoAmount: string - onClick?: () => void -} & TabProps - -const tabFocus = { borderWidth: '0' } -const tabBorderWidth = { base: 0, md: '1px' } -const cardBodyPx = { base: 6, md: 4 } -const cardFlexDirection: ResponsiveValue = { base: 'row', md: 'column' } -const flexMb = { base: 0, md: 6 } -const flexMr = { base: 2, md: 0 } - -export const FoxTab: React.FC = ({ - assetIcon, - assetSymbol, - fiatAmount, - cryptoAmount, - onClick, - ...props -}) => { - const bgHover = useColorModeValue('gray.100', 'gray.750') - - const tabSelected = useMemo( - () => ({ - bg: { base: 'none', md: bgHover }, - borderColor: 'primary', - borderWidth: { base: 0, md: '2px' }, - }), - [bgHover], - ) - - const tabHover = useMemo( - () => ({ textDecoration: 'none', bg: { base: 'none', md: bgHover } }), - [bgHover], - ) - - return ( - - - - - - - - - - - - - - ) -} diff --git a/src/plugins/foxPage/components/Governance.tsx b/src/plugins/foxPage/components/Governance.tsx deleted file mode 100644 index 4dd3427fcfd..00000000000 --- a/src/plugins/foxPage/components/Governance.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { - Badge, - Box, - Card, - CardBody, - CardHeader, - Flex, - Link, - Progress, - Skeleton, - Text as CText, - useColorModeValue, -} from '@chakra-ui/react' -import { getConfig } from 'config' -import { Amount } from 'components/Amount/Amount' -import { Text } from 'components/Text/Text' -import { bnOrZero } from 'lib/bignumber/bignumber' - -import { useGetGovernanceData } from '../hooks/getGovernanceData' - -const BOARDROOM_APP_BASE_URL = getConfig().REACT_APP_BOARDROOM_APP_BASE_URL -const SNAPSHOT_BASE_URL = getConfig().REACT_APP_SNAPSHOT_BASE_URL - -export const Governance = () => { - const linkColor = useColorModeValue('blue.500', 'blue.200') - const governanceData = useGetGovernanceData() - - return ( - - - - - - - - - - - - {governanceData?.data.map((proposal, i) => ( - - - - {proposal.title} - - {proposal.choices.map((choice, i) => ( - - - {choice} - - - - - - - - - - - ))} - - - ))} - - - ) -} diff --git a/src/plugins/foxPage/components/Layout.tsx b/src/plugins/foxPage/components/Layout.tsx deleted file mode 100644 index 5e269d41d80..00000000000 --- a/src/plugins/foxPage/components/Layout.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Box, Container, Text, useColorModeValue } from '@chakra-ui/react' -import type { ReactNode } from 'react' -import foxPageBg from 'assets/foxpage-bg.png' -import { AssetIcon } from 'components/AssetIcon' - -type FoxLayoutProps = { - children: ReactNode - icon: string - title: string - description: string -} - -const boxPy = { base: 8, md: 12 } -const boxMb = { base: 0, md: 4 } -const boxPx = { base: 0, md: 8 } -const boxDisplay = { base: 'none', md: 'block' } -const boxMinHeight = { base: '285px', sm: '235px', md: '190px' } -const containerPx = { base: 0, md: 16 } - -export const Layout = ({ children, icon, title, description }: FoxLayoutProps) => { - const descriptionColor = useColorModeValue('gray.750', 'whiteAlpha.700') - - return ( - <> - - - - - - {title} - - {description} - - - - - {children} - - - ) -} diff --git a/src/plugins/foxPage/components/MainOpportunity.tsx b/src/plugins/foxPage/components/MainOpportunity.tsx deleted file mode 100644 index 833f644c721..00000000000 --- a/src/plugins/foxPage/components/MainOpportunity.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import type { ResponsiveValue } from '@chakra-ui/react' -import { - Box, - Button, - Card, - CardBody, - CardHeader, - Flex, - Skeleton, - Text as CText, - useColorModeValue, -} from '@chakra-ui/react' -import type { ToAssetIdArgs } from '@shapeshiftoss/caip' -import { ethChainId } from '@shapeshiftoss/caip' -import { supportsETH } from '@shapeshiftoss/hdwallet-core/dist/wallet' -import type { Property } from 'csstype' -import { useMemo } from 'react' -import { Amount } from 'components/Amount/Amount' -import { AssetIcon } from 'components/AssetIcon' -import type { TextPropTypes } from 'components/Text/Text' -import { Text } from 'components/Text/Text' -import { useWallet } from 'hooks/useWallet/useWallet' -import { bnOrZero } from 'lib/bignumber/bignumber' -import { foxyAddresses } from 'lib/investor/investor-foxy' -import { toOpportunityId } from 'state/slices/opportunitiesSlice/utils' -import { - selectAggregatedEarnUserStakingOpportunityByStakingId, - selectAssetById, -} from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -type MainOpportunityProps = { - apy: string - assetId: string - balance: string - isLoaded: boolean - onClick: () => void - tvl: string -} - -const flexDirectionRow: ResponsiveValue = { base: 'column', md: 'row' } -const flexDirectionColumn: ResponsiveValue = { base: 'row', md: 'column' } -const alignItemsFlexStart = { base: 'center', md: 'flex-start' } - -export const MainOpportunity = ({ - apy, - assetId, - tvl, - balance, - onClick, - isLoaded, -}: MainOpportunityProps) => { - const { - state: { wallet, isDemoWallet }, - } = useWallet() - const greenColor = useColorModeValue('green.600', 'green.400') - const selectedAsset = useAppSelector(state => selectAssetById(state, assetId)) - if (!selectedAsset) throw new Error(`Asset not found for AssetId ${assetId}`) - - const toAssetIdParts: ToAssetIdArgs = { - assetNamespace: 'erc20', - assetReference: foxyAddresses[0].staking, - chainId: ethChainId, - } - - const opportunityId = toOpportunityId(toAssetIdParts) - const opportunityDataFilter = useMemo(() => { - return { - stakingId: opportunityId, - } - }, [opportunityId]) - - const foxyEarnOpportunityData = useAppSelector(state => - opportunityDataFilter - ? selectAggregatedEarnUserStakingOpportunityByStakingId(state, opportunityDataFilter) - : undefined, - ) - const hasActiveStaking = bnOrZero(foxyEarnOpportunityData?.stakedAmountCryptoBaseUnit).gt(0) - - const opportunityButtonTranslation = useMemo(() => { - if (isDemoWallet || !wallet || !supportsETH(wallet)) return 'common.connectWallet' - if (hasActiveStaking) return 'plugins.foxPage.manage' - return 'plugins.foxPage.getStarted' - }, [isDemoWallet, wallet, hasActiveStaking]) - - const isOpportunityButtonReady = useMemo( - () => Boolean(isDemoWallet || (wallet && !supportsETH(wallet)) || foxyEarnOpportunityData), - [isDemoWallet, wallet, foxyEarnOpportunityData], - ) - - const mainStakingTitleTranslation: TextPropTypes['translation'] = useMemo( - () => [ - 'plugins.foxPage.mainStakingTitle', - { - assetSymbol: selectedAsset.symbol, - }, - ], - [selectedAsset.symbol], - ) - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - {balance} - - - - - - - - - - - ) -} diff --git a/src/plugins/foxPage/components/OtherOpportunities/FoxOtherOpportunityPanel.tsx b/src/plugins/foxPage/components/OtherOpportunities/FoxOtherOpportunityPanel.tsx deleted file mode 100644 index 31dcbf61764..00000000000 --- a/src/plugins/foxPage/components/OtherOpportunities/FoxOtherOpportunityPanel.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { - AccordionButton, - AccordionIcon, - AccordionItem, - AccordionPanel, - Badge, - Box, - Flex, - useColorModeValue, -} from '@chakra-ui/react' -import { useMemo } from 'react' -import { useTranslate } from 'react-polyglot' -import type { DefiType } from 'state/slices/opportunitiesSlice/types' - -import type { ExternalOpportunity, OpportunityTypes } from '../../FoxCommon' -import { FoxOtherOpportunityPanelRow } from './FoxOtherOpportunityPanelRow' - -type FoxOtherOpportunityPanelProps = { - opportunities: ExternalOpportunity[] - title: string - type: OpportunityTypes | DefiType -} - -const accordionItemLast = { borderBottomWidth: 0 } - -export const FoxOtherOpportunityPanel: React.FC = ({ - opportunities, - title, -}) => { - const translate = useTranslate() - const borderColor = useColorModeValue('gray.150', 'gray.700') - - const renderRows = useMemo(() => { - return opportunities?.map((opportunity, index) => ( - - )) - }, [opportunities]) - - return ( - - - - {translate(title)} - - - - {opportunities.length} - - - - - - {renderRows} - - - ) -} diff --git a/src/plugins/foxPage/components/OtherOpportunities/FoxOtherOpportunityPanelRow.tsx b/src/plugins/foxPage/components/OtherOpportunities/FoxOtherOpportunityPanelRow.tsx deleted file mode 100644 index f9fa2893fef..00000000000 --- a/src/plugins/foxPage/components/OtherOpportunities/FoxOtherOpportunityPanelRow.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import { ExternalLinkIcon } from '@chakra-ui/icons' -import type { ResponsiveValue } from '@chakra-ui/react' -import { - Box, - Button, - Flex, - Link, - Skeleton, - Text as CText, - useColorModeValue, -} from '@chakra-ui/react' -import { ASSET_NAMESPACE, ethChainId, fromAssetId } from '@shapeshiftoss/caip' -import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import type { Property } from 'csstype' -import qs from 'qs' -import { useCallback, useMemo } from 'react' -import { useHistory, useLocation } from 'react-router' -import { Amount } from 'components/Amount/Amount' -import { AssetIcon } from 'components/AssetIcon' -import { Text } from 'components/Text/Text' -import { WalletActions } from 'context/WalletProvider/actions' -import { useWallet } from 'hooks/useWallet/useWallet' -import { bnOrZero } from 'lib/bignumber/bignumber' -import { trackOpportunityEvent } from 'lib/mixpanel/helpers' -import { MixPanelEvents } from 'lib/mixpanel/types' -import { DefiProvider, DefiType } from 'state/slices/opportunitiesSlice/types' -import { toOpportunityId } from 'state/slices/opportunitiesSlice/utils' -import { - selectAggregatedEarnUserLpOpportunity, - selectAggregatedEarnUserStakingOpportunityByStakingId, - selectAssets, -} from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -import type { ExternalOpportunity } from '../../FoxCommon' - -type FoxOtherOpportunityPanelRowProps = { - opportunity: ExternalOpportunity -} - -const flexWidth = { base: 'auto', md: '40%' } -const assetIconBoxSize = { base: 6, md: 8 } -const apyTextAlign: ResponsiveValue = { base: 'right', md: 'center' } -const opportunityButtonDisplay = { base: 'none', md: 'block' } - -export const FoxOtherOpportunityPanelRow: React.FC = ({ - opportunity, -}) => { - const { - state: { isDemoWallet, wallet }, - dispatch, - } = useWallet() - const assets = useAppSelector(selectAssets) - const opportunityId = useMemo( - () => - opportunity.contractAddress && - toOpportunityId({ - assetReference: opportunity.contractAddress, - assetNamespace: 'erc20', - chainId: ethChainId, - }), - [opportunity.contractAddress], - ) - - const earnOpportunity = useAppSelector(state => { - if (!opportunityId) return - - return opportunity.type === DefiType.LiquidityPool - ? selectAggregatedEarnUserLpOpportunity(state, { - assetId: opportunityId, - lpId: opportunityId, - }) - : selectAggregatedEarnUserStakingOpportunityByStakingId(state, { - stakingId: opportunityId, - }) - }) - - const hoverOpportunityBg = useColorModeValue('gray.100', 'gray.750') - const greenColor = useColorModeValue('green.600', 'green.400') - const hasActivePosition = bnOrZero(earnOpportunity?.cryptoAmountBaseUnit).gt(0) ?? false - const history = useHistory() - const location = useLocation() - const wrapperLinkProps = useMemo( - () => (earnOpportunity ? {} : { as: Link, isExternal: true, href: opportunity.link }), - [earnOpportunity, opportunity.link], - ) - - const handleClick = useCallback(() => { - if (opportunity.link) { - window.open(opportunity.link) - return - } - - if (isDemoWallet || !wallet || !supportsETH(wallet)) { - dispatch({ type: WalletActions.SET_WALLET_MODAL, payload: true }) - return - } - - if (earnOpportunity) { - const { chainId, contractAddress, rewardAddress } = earnOpportunity - trackOpportunityEvent( - MixPanelEvents.ClickOpportunity, - { - opportunity: earnOpportunity, - element: 'Table Row', - }, - assets, - ) - history.push({ - pathname: location.pathname, - search: qs.stringify({ - type: earnOpportunity.type, - provider: - opportunity.type === DefiType.LiquidityPool - ? DefiProvider.UniV2 - : DefiProvider.EthFoxStaking, - chainId, - contractAddress, - assetNamespace: ASSET_NAMESPACE.erc20, - assetReference: earnOpportunity.underlyingAssetId - ? fromAssetId(earnOpportunity.underlyingAssetId).assetReference - : undefined, - highestBalanceAccountAddress: opportunity.highestBalanceAccountAddress, - rewardId: rewardAddress, - modal: 'overview', - }), - state: { background: location }, - }) - return - } - }, [ - opportunity.link, - opportunity.type, - opportunity.highestBalanceAccountAddress, - isDemoWallet, - wallet, - earnOpportunity, - dispatch, - assets, - history, - location, - ]) - - const opportunityButtonTranslation = useMemo(() => { - if (opportunity.link) return 'plugins.foxPage.getStarted' - if (isDemoWallet || !wallet || !supportsETH(wallet)) return 'common.connectWallet' - - return hasActivePosition ? 'plugins.foxPage.manage' : 'plugins.foxPage.getStarted' - }, [isDemoWallet, opportunity.link, hasActivePosition, wallet]) - - const isOpportunityButtonReady = useMemo( - () => Boolean(isDemoWallet || (wallet && !supportsETH(wallet)) || earnOpportunity), - [isDemoWallet, wallet, earnOpportunity], - ) - - const hoverStyle = useMemo( - () => ({ bg: hoverOpportunityBg, textDecoration: 'none' }), - [hoverOpportunityBg], - ) - - if (!opportunity) return null - - return ( - - - {opportunity.icons?.map((iconSrc, i, icons) => ( - - ))} - - {opportunity.name} - - - - - - - {opportunity.apy ? : '--'} - - - - - - {earnOpportunity ? ( - - ) : ( - - )} - - - - ) -} diff --git a/src/plugins/foxPage/components/OtherOpportunities/OtherOpportunities.tsx b/src/plugins/foxPage/components/OtherOpportunities/OtherOpportunities.tsx deleted file mode 100644 index d3a486aee1b..00000000000 --- a/src/plugins/foxPage/components/OtherOpportunities/OtherOpportunities.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Accordion, Card, CardHeader, Flex } from '@chakra-ui/react' -import type { OpportunitiesBucket } from 'plugins/foxPage/FoxCommon' -import { useMemo } from 'react' -import { Text } from 'components/Text/Text' - -import { FoxOtherOpportunityPanel } from './FoxOtherOpportunityPanel' - -type OtherOpportunitiesProps = { - title: string - description: string - opportunities: OpportunitiesBucket[] -} - -const defaultIndex = [0] - -export const OtherOpportunities: React.FC = ({ - title, - description, - opportunities, -}) => { - const renderRows = useMemo(() => { - return opportunities.map(opportunitiesBucket => { - const { opportunities } = opportunitiesBucket - if (!opportunities.length || opportunities.every(opportunity => opportunity.isDisabled)) - return null - - return ( - - ) - }) - }, [opportunities]) - - return ( - - - - - - - - - {renderRows} - - - ) -} diff --git a/src/plugins/foxPage/components/Total.tsx b/src/plugins/foxPage/components/Total.tsx deleted file mode 100644 index e564fce1aa3..00000000000 --- a/src/plugins/foxPage/components/Total.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import type { ResponsiveValue } from '@chakra-ui/react' -import { Flex, SkeletonText, Text } from '@chakra-ui/react' -import type { Property } from 'csstype' -import { useTranslate } from 'react-polyglot' -import { Amount } from 'components/Amount/Amount' -import { AssetIcon } from 'components/AssetIcon' - -type TotalProps = { - icons: string[] - fiatAmount: string -} - -const flexDirection: ResponsiveValue = { base: 'row-reverse', md: 'column' } -const alignItems = { base: 'center', md: 'flex-start' } -const justifyContent = { base: 'space-between', md: 'flex-start' } -const flexMb = { base: 0, md: 6 } - -export const Total = ({ icons, fiatAmount }: TotalProps) => { - const translate = useTranslate() - - return ( - - - {icons.map((icon, index) => ( - 0 ? '-3.5' : 0} - /> - ))} - - - - {translate('plugins.foxPage.totalFoxValue')} - - - - - ) -} diff --git a/src/plugins/foxPage/components/TradeOpportunities.tsx b/src/plugins/foxPage/components/TradeOpportunities.tsx deleted file mode 100644 index 135befe59fe..00000000000 --- a/src/plugins/foxPage/components/TradeOpportunities.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Box, Card, CardBody, CardHeader, Flex, Image, Link, Text as CText } from '@chakra-ui/react' -import { useTranslate } from 'react-polyglot' -import { Text } from 'components/Text/Text' - -type TradeOpportunity = { - link: string - icon: string -} - -export type TradeOpportunitiesBucket = { - title: string - opportunities: TradeOpportunity[] -} - -type TradeOpportunitiesProps = { - opportunities: TradeOpportunitiesBucket[] -} - -export const TradeOpportunities: React.FC = ({ opportunities }) => { - const translate = useTranslate() - - return ( - - - - {translate('plugins.foxPage.availableToTradeOn')} - - - - {opportunities.map((bucket, index) => ( - - - - {bucket.opportunities.map((opportunity, index) => ( - - - - ))} - - - ))} - - - ) -} diff --git a/src/plugins/foxPage/foxPage.tsx b/src/plugins/foxPage/foxPage.tsx deleted file mode 100644 index a42a24d8ff2..00000000000 --- a/src/plugins/foxPage/foxPage.tsx +++ /dev/null @@ -1,357 +0,0 @@ -import { ChevronDownIcon } from '@chakra-ui/icons' -import type { StackDirection } from '@chakra-ui/react' -import { - Box, - Button, - Menu, - MenuButton, - MenuItem, - MenuList, - SimpleGrid, - Stack, - TabList, - TabPanel, - TabPanels, - Tabs, - useColorModeValue, - useMediaQuery, -} from '@chakra-ui/react' -import type { AssetId, ToAssetIdArgs } from '@shapeshiftoss/caip' -import { ethChainId, foxAssetId, foxyAssetId } from '@shapeshiftoss/caip' -import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import qs from 'qs' -import { useCallback, useMemo } from 'react' -import { useTranslate } from 'react-polyglot' -import { useHistory, useLocation } from 'react-router' -import { AssetMarketData } from 'components/AssetHeader/AssetMarketData' -import { SEO } from 'components/Layout/Seo' -import { WalletActions } from 'context/WalletProvider/actions' -import { useRouteAssetId } from 'hooks/useRouteAssetId/useRouteAssetId' -import { useWallet } from 'hooks/useWallet/useWallet' -import { bn, bnOrZero } from 'lib/bignumber/bignumber' -import { foxyAddresses } from 'lib/investor/investor-foxy' -import { trackOpportunityEvent } from 'lib/mixpanel/helpers' -import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton' -import { MixPanelEvents } from 'lib/mixpanel/types' -import { useGetFoxyAprQuery } from 'state/apis/foxy/foxyApi' -import { useGetAssetDescriptionQuery } from 'state/slices/assetsSlice/assetsSlice' -import { DefiProvider } from 'state/slices/opportunitiesSlice/types' -import { toOpportunityId } from 'state/slices/opportunitiesSlice/utils' -import { - selectAggregatedEarnUserStakingOpportunityByStakingId, - selectAssetById, - selectAssets, - selectPortfolioCryptoPrecisionBalanceByFilter, - selectPortfolioUserCurrencyBalanceByAssetId, - selectSelectedLocale, -} from 'state/slices/selectors' -import { useAppSelector } from 'state/store' -import { breakpoints } from 'theme/theme' - -import { AssetActions } from './components/AssetActions' -import { BondProtocolCta } from './components/BondProtocolCta' -import { DappBack } from './components/DappBack' -import { FoxChart } from './components/FoxChart' -import { FoxTab } from './components/FoxTab' -import { Governance } from './components/Governance' -import { Layout } from './components/Layout' -import { MainOpportunity } from './components/MainOpportunity' -import { OtherOpportunities } from './components/OtherOpportunities/OtherOpportunities' -import { Total } from './components/Total' -import type { TradeOpportunitiesBucket } from './components/TradeOpportunities' -import { TradeOpportunities } from './components/TradeOpportunities' -import { foxTradeOpportunitiesBuckets, foxyTradeOpportunitiesBuckets } from './FoxCommon' -import { useOtherOpportunities } from './hooks/useOtherOpportunities' - -const gridTemplateColumns = { base: 'repeat(1, 1fr)', lg: 'repeat(3, 1fr)' } -const boxMxProps = { base: 4, md: 0 } -const tabPanelDirectionProps: StackDirection = { base: 'column', xl: 'row' } -const stackMaxWidthProps = { base: 'full', lg: 'sm' } - -export enum FoxPageRoutes { - Fox = '/fox/fox', - Foxy = '/fox/foxy', -} - -const assetsRoutes: Record = { - [foxAssetId]: FoxPageRoutes.Fox, - [foxyAssetId]: FoxPageRoutes.Foxy, -} - -const assetsTradeOpportunitiesBuckets: Record = { - [foxAssetId]: foxTradeOpportunitiesBuckets, - [foxyAssetId]: foxyTradeOpportunitiesBuckets, -} - -const chevronDownIcon = - -export const FoxPage = () => { - const { - state: { wallet }, - dispatch, - } = useWallet() - const translate = useTranslate() - const history = useHistory() - const location = useLocation() - const mixpanel = getMixPanel() - - const activeAssetId = useRouteAssetId() - const allAssets = useAppSelector(selectAssets) - // TODO(gomes): Use useRouteAssetId and selectAssetById programmatically - const assetFox = useAppSelector(state => selectAssetById(state, foxAssetId)) - const assetFoxy = useAppSelector(state => selectAssetById(state, foxyAssetId)) - if (!assetFox) throw new Error(`Asset not found for AssetId ${foxAssetId}`) - if (!assetFoxy) throw new Error(`Asset not found for AssetId ${foxyAssetId}`) - - const otherOpportunities = useOtherOpportunities(activeAssetId) - - const assets = useMemo(() => [assetFox, assetFoxy], [assetFox, assetFoxy]) - - const selectedAssetIndex = useMemo( - () => assets.findIndex(asset => asset?.assetId === activeAssetId), - [activeAssetId, assets], - ) - - const selectedAsset = assets[selectedAssetIndex] - - const foxFilter = useMemo(() => ({ assetId: foxAssetId }), []) - const foxyFilter = useMemo(() => ({ assetId: foxyAssetId }), []) - const fiatBalanceFox = - useAppSelector(s => selectPortfolioUserCurrencyBalanceByAssetId(s, foxFilter)) ?? '0' - const fiatBalanceFoxy = - useAppSelector(s => selectPortfolioUserCurrencyBalanceByAssetId(s, foxyFilter)) ?? '0' - const cryptoHumanBalanceFox = - useAppSelector(s => selectPortfolioCryptoPrecisionBalanceByFilter(s, foxFilter)) ?? '0' - const cryptoHumanBalanceFoxy = - useAppSelector(s => selectPortfolioCryptoPrecisionBalanceByFilter(s, foxyFilter)) ?? '0' - - const fiatBalances = useMemo( - () => [fiatBalanceFox, fiatBalanceFoxy], - [fiatBalanceFox, fiatBalanceFoxy], - ) - - const cryptoHumanBalances = useMemo( - () => [cryptoHumanBalanceFox, cryptoHumanBalanceFoxy], - [cryptoHumanBalanceFox, cryptoHumanBalanceFoxy], - ) - - const { data: foxyAprData, isLoading: isFoxyAprLoading } = useGetFoxyAprQuery() - - const totalFiatBalance = bnOrZero(fiatBalanceFox).plus(bnOrZero(fiatBalanceFoxy)).toString() - - const [isLargerThanMd] = useMediaQuery(`(min-width: ${breakpoints['md']})`, { ssr: false }) - const mobileTabBg = useColorModeValue('gray.100', 'gray.750') - const description = - selectedAsset.assetId === foxAssetId - ? translate('plugins.foxPage.foxDescription') // FOX has a custom description, other assets can use the asset-service one - : selectedAsset.description - - const selectedLocale = useAppSelector(selectSelectedLocale) - // TODO(gomes): Export a similar RTK select() query, consumed to determine wallet + staking balance loaded - const getAssetDescriptionQuery = useGetAssetDescriptionQuery({ - assetId: selectedAsset.assetId, - selectedLocale, - }) - const isAssetDescriptionLoaded = !getAssetDescriptionQuery.isLoading - - const toAssetIdParts: ToAssetIdArgs = { - assetNamespace: 'erc20', - assetReference: foxyAddresses[0].staking, - chainId: ethChainId, - } - - const opportunityId = toOpportunityId(toAssetIdParts) - const opportunityDataFilter = useMemo(() => { - return { - stakingId: opportunityId, - } - }, [opportunityId]) - - const foxyEarnOpportunityData = useAppSelector(state => - opportunityDataFilter - ? selectAggregatedEarnUserStakingOpportunityByStakingId(state, opportunityDataFilter) - : undefined, - ) - - const totalIcons = useMemo(() => [assetFox.icon, assetFoxy.icon], [assetFox, assetFoxy]) - - const handleTabClick = useCallback( - (assetId: AssetId, assetName: string) => { - if (assetId === activeAssetId) { - return - } - mixpanel?.track(MixPanelEvents.Click, { element: `${assetName} toggle` }) - history.push(assetsRoutes[assetId]) - }, - [activeAssetId, history, mixpanel], - ) - - const handleOpportunityClick = useCallback(() => { - if (!foxyEarnOpportunityData) return - if (!wallet || !supportsETH(wallet)) { - dispatch({ type: WalletActions.SET_WALLET_MODAL, payload: true }) - return - } - - trackOpportunityEvent( - MixPanelEvents.ClickOpportunity, - { - opportunity: foxyEarnOpportunityData, - element: 'Fox Page Row', - }, - allAssets, - ) - - history.push({ - pathname: location.pathname, - search: qs.stringify({ - provider: DefiProvider.ShapeShift, - chainId: assetFoxy.chainId, - assetNamespace: 'erc20', - contractAddress: foxyAddresses[0].foxy, - assetReference: foxyAddresses[0].staking, - rewardId: foxyAddresses[0].foxy, - modal: 'overview', - }), - state: { background: location }, - }) - }, [allAssets, assetFoxy.chainId, dispatch, foxyEarnOpportunityData, history, location, wallet]) - - const mdFoxTabs = useMemo( - () => - assets.map((asset, index) => ( - handleTabClick(asset.assetId, asset.name)} - /> - )), - [assets, cryptoHumanBalances, fiatBalances, handleTabClick], - ) - - const smFoxTabs = useMemo( - () => - assets.map((asset, index) => ( - // eslint-disable-next-line react-memo/require-usememo - handleTabClick(asset.assetId, asset.name)}> - - - )), - [assets, cryptoHumanBalances, fiatBalances, handleTabClick], - ) - - if (!isAssetDescriptionLoaded || !activeAssetId) return null - if (wallet && supportsETH(wallet) && !foxyEarnOpportunityData) return null - - return ( - - - - - - - {isLargerThanMd && mdFoxTabs} - {!isLargerThanMd && ( - - - - - {selectedAsset && ( - - )} - - - {smFoxTabs} - - - )} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) -} diff --git a/src/plugins/foxPage/hooks/getGovernanceData.test.ts b/src/plugins/foxPage/hooks/getGovernanceData.test.ts deleted file mode 100644 index 6e922c1765d..00000000000 --- a/src/plugins/foxPage/hooks/getGovernanceData.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import type { BoardroomGovernanceResult } from './getGovernanceData' -import { parseGovernanceData } from './getGovernanceData' - -const EMPTY_RESULTS_PROPOSAL: BoardroomGovernanceResult = { - refId: 'refId1', - title: 'Proposal 1', - currentState: 'active', - choices: ['YES', 'NO'], - indexedResult: [], -} -const PARTIAL_RESULTS_PROPOSAL: BoardroomGovernanceResult = { - refId: 'refId2', - title: 'Proposal 2', - currentState: 'active', - choices: ['YES', 'NO'], - indexedResult: [ - { - total: 362512.22, - choice: 0, - }, - ], -} - -const ALL_RESULTS_PROPOSAL: BoardroomGovernanceResult = { - refId: 'refId3', - title: 'Proposal 3', - currentState: 'closed', - choices: ['Yes (For)', 'No (Against)'], - indexedResult: [ - { - total: 4122544.5, - choice: 0, - }, - { - total: 200, - choice: 1, - }, - ], -} - -const INACTIVE_PROPOSAL: BoardroomGovernanceResult = { - refId: 'refId4', - title: 'Proposal 4', - currentState: 'closed', - choices: ['For', 'Against'], - indexedResult: [ - { - total: 5876468, - choice: 0, - }, - ], -} - -const INACTIVE_PROPOSAL_TWO: BoardroomGovernanceResult = { - refId: 'refId5', - title: 'Proposal 5', - currentState: 'closed', - choices: ['For', 'Against'], - indexedResult: [ - { - total: 5876468, - choice: 0, - }, - ], -} - -describe('parseGovernanceData', () => { - const ZERO_RESULT = { - absolute: '0', - percent: '0', - } - it('populates and zeros out boardroom response with no results', () => { - const data = [EMPTY_RESULTS_PROPOSAL] - const parsedData = parseGovernanceData(data) - expect(parsedData).toHaveLength(1) - expect(parsedData[0].results).toHaveLength(2) - expect(parsedData[0].results[0]).toMatchObject(ZERO_RESULT) - expect(parsedData[0].results[1]).toMatchObject(ZERO_RESULT) - }) - it('populates and zeros out the missing result items of a boardroom response with partial results', () => { - const data = [PARTIAL_RESULTS_PROPOSAL] - const parsedData = parseGovernanceData(data) - expect(parsedData).toHaveLength(1) - expect(parsedData[0].results).toHaveLength(2) - expect(parsedData[0].results[0]).toMatchObject({ - absolute: '362512.22', - percent: '1', - }) - expect(parsedData[0].results[1]).toMatchObject(ZERO_RESULT) - }) - it('parses a boardroom response with results for all choices', () => { - const data = [ALL_RESULTS_PROPOSAL] - const parsedData = parseGovernanceData(data) - expect(parsedData).toHaveLength(1) - expect(parsedData[0].results).toHaveLength(2) - expect(parsedData[0].results[0]).toMatchObject({ - absolute: '4122544.5', - percent: '0.99995148862608391085', - }) - expect(parsedData[0].results[1]).toMatchObject({ - absolute: '200', - percent: '0.00004851137391608915', - }) - }) - it('builds a parsed response with the latest inactive proposal if all inactive', () => { - const data = [INACTIVE_PROPOSAL, INACTIVE_PROPOSAL_TWO, ALL_RESULTS_PROPOSAL] - const parsedData = parseGovernanceData(data) - expect(parsedData).toHaveLength(1) - expect(parsedData[0].results).toHaveLength(2) - expect(parsedData[0].refId).toEqual(INACTIVE_PROPOSAL.refId) - expect(parsedData[0].results[0]).toMatchObject({ - absolute: '5876468', - percent: '1', - }) - }) - it('builds a parsed response with all active proposals', () => { - const data = [EMPTY_RESULTS_PROPOSAL, PARTIAL_RESULTS_PROPOSAL] - const parsedData = parseGovernanceData(data) - expect(parsedData).toHaveLength(2) - expect(parsedData[0].results).toHaveLength(2) - expect(parsedData[0].refId).toEqual(EMPTY_RESULTS_PROPOSAL.refId) - expect(parsedData[1].refId).toEqual(PARTIAL_RESULTS_PROPOSAL.refId) - expect(parsedData[0].results[0]).toMatchObject(ZERO_RESULT) - expect(parsedData[1].results[0]).toMatchObject({ - absolute: '362512.22', - percent: '1', - }) - }) -}) diff --git a/src/plugins/foxPage/hooks/getGovernanceData.ts b/src/plugins/foxPage/hooks/getGovernanceData.ts deleted file mode 100644 index a3197865cb8..00000000000 --- a/src/plugins/foxPage/hooks/getGovernanceData.ts +++ /dev/null @@ -1,78 +0,0 @@ -import axios from 'axios' -import { getConfig } from 'config' -import { useEffect, useState } from 'react' -import { bnOrZero } from 'lib/bignumber/bignumber' - -// Non-exhaustive typings. We do not want to keep this a 1/1 mapping to an external API -export type BoardroomGovernanceResult = { - currentState: string - title: string - choices: string[] - indexedResult: { total: number; choice: number }[] - refId: string -} - -export type ParsedBoardroomGovernanceResult = { - refId: string - title: string - choices: string[] - results: { - absolute: string - percent: string - }[] -} - -const BOARDROOM_API_BASE_URL = getConfig().REACT_APP_BOARDROOM_API_BASE_URL - -export const parseGovernanceData = ( - governanceData: BoardroomGovernanceResult[], -): ParsedBoardroomGovernanceResult[] => { - const activeProposals = governanceData.filter(data => data.currentState === 'active') - const proposals = activeProposals.length ? activeProposals : [governanceData[0]] - - return proposals.map(({ title, choices, indexedResult, refId }) => { - const totalResults = indexedResult.reduce((acc, currentResult) => { - acc = acc.plus(currentResult.total) - return acc - }, bnOrZero('0')) - - return { - refId, - title, - choices, - results: choices.map((_, i) => ({ - absolute: bnOrZero(indexedResult[i]?.total).toString(), - percent: indexedResult[i] - ? bnOrZero(indexedResult[i].total).div(totalResults).toString() - : '0', - })), - } - }) -} - -export const useGetGovernanceData = () => { - const [data, setData] = useState>([]) - const [error, setError] = useState() - const [loaded, setLoaded] = useState(false) - - useEffect(() => { - const loadGovernanceData = async () => { - try { - const response = await axios.get<{ data: BoardroomGovernanceResult[] }>( - `${BOARDROOM_API_BASE_URL}proposals`, - ) - const governanceData = response?.data?.data - const parsedGovernanceData = parseGovernanceData(governanceData) - setData(parsedGovernanceData) - } catch (e) { - setError(e) - } finally { - setLoaded(true) - } - } - - loadGovernanceData() - }, []) - - return { data, error, loaded } -} diff --git a/src/plugins/foxPage/hooks/useOtherOpportunities.ts b/src/plugins/foxPage/hooks/useOtherOpportunities.ts deleted file mode 100644 index d2bccee0834..00000000000 --- a/src/plugins/foxPage/hooks/useOtherOpportunities.ts +++ /dev/null @@ -1,154 +0,0 @@ -import type { AssetId } from '@shapeshiftoss/caip' -import { foxAssetId, foxyAssetId, fromAccountId, fromAssetId } from '@shapeshiftoss/caip' -import { useMemo } from 'react' -import { bnOrZero } from 'lib/bignumber/bignumber' -import { foxyAddresses } from 'lib/investor/investor-foxy' -import { foxEthLpAssetId, foxEthStakingAssetIdV8 } from 'state/slices/opportunitiesSlice/constants' -import type { StakingId } from 'state/slices/opportunitiesSlice/types' -import { DefiType } from 'state/slices/opportunitiesSlice/types' -import { - selectAggregatedEarnUserLpOpportunity, - selectHighestBalanceAccountIdByLpId, - selectHighestBalanceAccountIdByStakingId, - selectLpOpportunitiesById, - selectStakingOpportunitiesById, -} from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -import type { OpportunitiesBucket } from '../FoxCommon' -import { OpportunityTypes } from '../FoxCommon' - -export const useOtherOpportunities = (assetId: AssetId) => { - const highestFarmingBalanceAccountIdFilter = useMemo( - () => ({ - stakingId: foxEthStakingAssetIdV8 as StakingId, - }), - [], - ) - const highestFarmingBalanceAccountId = useAppSelector(state => - selectHighestBalanceAccountIdByStakingId(state, highestFarmingBalanceAccountIdFilter), - ) - - const lpOpportunitiesById = useAppSelector(selectLpOpportunitiesById) - - const defaultLpOpportunityData = useMemo( - () => lpOpportunitiesById[foxEthLpAssetId], - [lpOpportunitiesById], - ) - const lpOpportunityId = foxEthLpAssetId - const highestBalanceLpAccountIdFilter = useMemo( - () => ({ lpId: lpOpportunityId }), - [lpOpportunityId], - ) - const highestBalanceLpAccountId = useAppSelector(state => - selectHighestBalanceAccountIdByLpId(state, highestBalanceLpAccountIdFilter), - ) - - const foxEthLpOpportunityFilter = useMemo( - () => ({ - lpId: foxEthLpAssetId, - assetId: foxEthLpAssetId, - }), - [], - ) - const foxEthLpOpportunity = useAppSelector(state => - selectAggregatedEarnUserLpOpportunity(state, foxEthLpOpportunityFilter), - ) - - const stakingOpportunities = useAppSelector(selectStakingOpportunitiesById) - - const foxFarmingOpportunityMetadata = useMemo( - () => stakingOpportunities[foxEthStakingAssetIdV8 as StakingId], - [stakingOpportunities], - ) - - const otherOpportunities = useMemo(() => { - const opportunities: Record = { - [foxAssetId]: [ - { - type: DefiType.Staking, - title: 'plugins.foxPage.farming', - opportunities: [ - ...(foxFarmingOpportunityMetadata - ? [ - { - ...foxFarmingOpportunityMetadata, - apy: Boolean(defaultLpOpportunityData && foxFarmingOpportunityMetadata) - ? bnOrZero(foxFarmingOpportunityMetadata?.apy) - .plus(defaultLpOpportunityData?.apy ?? 0) - .toString() - : undefined, - contractAddress: fromAssetId(foxFarmingOpportunityMetadata.assetId) - .assetReference, - highestBalanceAccountAddress: - highestFarmingBalanceAccountId && - fromAccountId(highestFarmingBalanceAccountId).account, - }, - ] - : []), - ], - }, - { - type: DefiType.LiquidityPool, - title: 'plugins.foxPage.liquidityPools', - opportunities: [ - ...(foxEthLpOpportunity - ? [ - { - ...foxEthLpOpportunity, - type: DefiType.LiquidityPool, - contractAddress: fromAssetId(foxEthLpAssetId).assetReference, - highestBalanceAccountAddress: - highestBalanceLpAccountId && fromAccountId(highestBalanceLpAccountId).account, - }, - ] - : []), - ], - }, - { - type: OpportunityTypes.BorrowingAndLending, - title: 'plugins.foxPage.borrowingAndLending', - opportunities: [ - { - name: 'FOX', - isLoaded: true, - apy: null, - link: 'https://app.rari.capital/fuse/pool/79', - icons: ['https://assets.coincap.io/assets/icons/256/fox.png'], - isDisabled: true, - }, - ], - }, - ], - [foxyAssetId]: [ - { - type: OpportunityTypes.LiquidityPool, - title: 'plugins.foxPage.liquidityPools', - opportunities: [ - { - name: 'ElasticSwap', - contractAddress: foxyAddresses[0].staking, - isLoaded: true, // No network request here - apy: null, - link: 'https://elasticswap.org/#/liquidity', - icons: [ - 'https://raw.githubusercontent.com/shapeshift/lib/main/packages/asset-service/src/generateAssetData/ethereum/icons/foxy-icon.png', - ], - }, - ], - }, - ], - } - - return opportunities[assetId] - }, [ - assetId, - defaultLpOpportunityData, - foxFarmingOpportunityMetadata, - foxEthLpOpportunity, - highestBalanceLpAccountId, - highestFarmingBalanceAccountId, - ]) - - return otherOpportunities -} diff --git a/src/plugins/foxPage/images/binance.png b/src/plugins/foxPage/images/binance.png deleted file mode 100644 index 95148ff7ec5..00000000000 Binary files a/src/plugins/foxPage/images/binance.png and /dev/null differ diff --git a/src/plugins/foxPage/images/coinbase.png b/src/plugins/foxPage/images/coinbase.png deleted file mode 100644 index 931b11d2e92..00000000000 Binary files a/src/plugins/foxPage/images/coinbase.png and /dev/null differ diff --git a/src/plugins/foxPage/images/elasticswap.png b/src/plugins/foxPage/images/elasticswap.png deleted file mode 100644 index efa7d195cb5..00000000000 Binary files a/src/plugins/foxPage/images/elasticswap.png and /dev/null differ diff --git a/src/plugins/foxPage/images/thorswap.png b/src/plugins/foxPage/images/thorswap.png deleted file mode 100644 index dd0f00bba04..00000000000 Binary files a/src/plugins/foxPage/images/thorswap.png and /dev/null differ diff --git a/src/plugins/foxPage/images/uniswap.png b/src/plugins/foxPage/images/uniswap.png deleted file mode 100644 index 50c6dc8ae8d..00000000000 Binary files a/src/plugins/foxPage/images/uniswap.png and /dev/null differ diff --git a/src/plugins/foxPage/index.tsx b/src/plugins/foxPage/index.tsx deleted file mode 100644 index 3b9776b9061..00000000000 --- a/src/plugins/foxPage/index.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { type Plugins } from 'plugins/types' -import { RouteCategory } from 'Routes/helpers' -import { FoxIcon } from 'components/Icons/FoxIcon' - -import { FoxPage } from './foxPage' - -// eslint-disable-next-line import/no-default-export -export default function register(): Plugins { - return [ - [ - 'foxPage', - { - name: 'foxPage', - icon: , - routes: [ - { - path: '/fox', - label: 'navBar.foxToken', - main: () => , - icon: , - category: RouteCategory.Explore, - hide: true, - routes: [ - { - path: '/fox', - label: 'navBar.foxToken', - main: () => , - }, - { - path: '/foxy', - label: 'navBar.foxToken', - main: () => , - }, - ], - }, - ], - }, - ], - ] -} diff --git a/src/plugins/foxPage/utils/getFoxPageRouteAssetId.ts b/src/plugins/foxPage/utils/getFoxPageRouteAssetId.ts deleted file mode 100644 index 4ad3be90b1d..00000000000 --- a/src/plugins/foxPage/utils/getFoxPageRouteAssetId.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { foxAssetId, foxyAssetId } from '@shapeshiftoss/caip' -import { matchPath } from 'react-router' - -const FOX_PAGE_DEFAULT_ASSET = 'fox' - -export const getFoxPageRouteAssetId = (pathname: string) => { - const foxPageAssetIdPathMatch = matchPath<{ foxAsset?: 'fox' | 'foxy' }>(pathname, { - path: '/fox/:foxAsset?', - }) - - const foxAsset = foxPageAssetIdPathMatch?.params?.foxAsset ?? FOX_PAGE_DEFAULT_ASSET - - return foxAsset === 'fox' ? foxAssetId : foxyAssetId -}