diff --git a/apps/cowswap-frontend/src/common/containers/CoWAmmBanner/useVampireAttack.ts b/apps/cowswap-frontend/src/common/containers/CoWAmmBanner/useVampireAttack.ts
deleted file mode 100644
index e6bec7d64c..0000000000
--- a/apps/cowswap-frontend/src/common/containers/CoWAmmBanner/useVampireAttack.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { useAtomValue } from 'jotai'
-import { useMemo } from 'react'
-
-import { LP_TOKEN_LIST_COW_AMM_ONLY, useAllLpTokens } from '@cowprotocol/tokens'
-import { LpTokenProvider } from '@cowprotocol/types'
-
-import { useLpTokensWithBalances, usePoolsInfo } from 'modules/yield/shared'
-import { POOLS_AVERAGE_DATA_MOCK } from 'modules/yield/updaters/PoolsInfoUpdater/mockPoolInfo'
-
-import { TokenWithAlternative, TokenWithSuperiorAlternative, VampireAttackContext } from './types'
-
-import { useSafeMemoObject } from '../../hooks/useSafeMemo'
-import { areLpBalancesLoadedAtom } from '../../updaters/LpBalancesAndAllowancesUpdater'
-
-export function useVampireAttack(): VampireAttackContext | null {
- const { tokens: lpTokensWithBalances, count: lpTokensWithBalancesCount } = useLpTokensWithBalances()
- const cowAmmLpTokens = useAllLpTokens(LP_TOKEN_LIST_COW_AMM_ONLY)
- const poolsInfo = usePoolsInfo()
- const areLpBalancesLoaded = useAtomValue(areLpBalancesLoadedAtom)
-
- const alternativesResult = useMemo(() => {
- if (lpTokensWithBalancesCount === 0) return null
-
- const result = Object.keys(lpTokensWithBalances).reduce(
- (acc, tokenAddress) => {
- const { token: lpToken, balance: tokenBalance } = lpTokensWithBalances[tokenAddress]
- const alternative = cowAmmLpTokens.find((cowAmmLpToken) => {
- return cowAmmLpToken.tokens.every((token) => lpToken.tokens.includes(token))
- })
-
- if (alternative) {
- const tokenPoolInfo = poolsInfo?.[lpToken.address.toLowerCase()]?.info
- const alternativePoolInfo = poolsInfo?.[alternative.address.toLowerCase()]?.info
-
- // When CoW AMM pool has better APY
- if (alternativePoolInfo?.apy && tokenPoolInfo?.apy && alternativePoolInfo.apy > tokenPoolInfo.apy) {
- acc.superiorAlternatives.push({
- token: lpToken,
- alternative,
- tokenPoolInfo,
- alternativePoolInfo,
- tokenBalance,
- })
- } else {
- acc.alternatives.push({ token: lpToken, alternative, tokenBalance })
- }
- }
-
- return acc
- },
- { superiorAlternatives: [] as TokenWithSuperiorAlternative[], alternatives: [] as TokenWithAlternative[] },
- )
-
- return {
- superiorAlternatives: result.superiorAlternatives.sort((a, b) => {
- if (!b.tokenPoolInfo || !a.tokenPoolInfo) return 0
-
- return b.tokenPoolInfo.apy - a.tokenPoolInfo.apy
- }),
- alternatives: result.alternatives.sort((a, b) => {
- const aBalance = lpTokensWithBalances[a.token.address.toLowerCase()].balance
- const bBalance = lpTokensWithBalances[b.token.address.toLowerCase()].balance
-
- return +bBalance.sub(aBalance).toString()
- }),
- }
- }, [lpTokensWithBalancesCount, lpTokensWithBalances, cowAmmLpTokens, poolsInfo])
-
- const averageApy = useMemo(() => {
- const keys = Object.keys(POOLS_AVERAGE_DATA_MOCK)
- let count = 0
-
- return (
- keys.reduce((result, _key) => {
- const key = _key as LpTokenProvider
-
- if (key === LpTokenProvider.COW_AMM) return result
-
- count++
- const pool = POOLS_AVERAGE_DATA_MOCK[key]
-
- return result + (pool?.apy || 0)
- }, 0) / count
- )
- }, [])
-
- const { [LpTokenProvider.COW_AMM]: cowAmmData, ...poolsAverageData } = POOLS_AVERAGE_DATA_MOCK
- const averageApyDiff = cowAmmData ? +(cowAmmData.apy - averageApy).toFixed(2) : 0
-
- const context = useSafeMemoObject({
- superiorAlternatives: alternativesResult?.superiorAlternatives || null,
- alternatives: alternativesResult?.alternatives || null,
- cowAmmLpTokensCount: cowAmmLpTokens.length,
- poolsAverageData,
- averageApyDiff,
- })
-
- if (cowAmmLpTokens.length === 0 || !areLpBalancesLoaded) return null
-
- return context
-}
diff --git a/apps/cowswap-frontend/src/common/updaters/LpBalancesAndAllowancesUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/LpBalancesAndAllowancesUpdater.tsx
index 1ce5c28e8e..939a7f5b81 100644
--- a/apps/cowswap-frontend/src/common/updaters/LpBalancesAndAllowancesUpdater.tsx
+++ b/apps/cowswap-frontend/src/common/updaters/LpBalancesAndAllowancesUpdater.tsx
@@ -50,5 +50,9 @@ export function LpBalancesAndAllowancesUpdater({ account, chainId, enablePolling
return () => clearTimeout(timeout)
}, [])
+ useEffect(() => {
+ setAreLpBalancesLoaded(false)
+ }, [account, setAreLpBalancesLoaded])
+
return null
}
diff --git a/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/elements.tsx b/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/elements.tsx
index cc03577e42..7b4411d9a0 100644
--- a/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/elements.tsx
+++ b/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/elements.tsx
@@ -29,7 +29,7 @@ export const CoWAmmInlineBanner = ({ token, apyDiff }: { token: LpToken | undefi
{token && apyDiff && apyDiff > 0 ? (
<>
Convert your LP tokens into CoW AMM pools and earn up to{' '}
- +{apyDiff}% more yield compared to . Or, swap
+ +{apyDiff.toFixed(1)}% more yield compared to . Or, swap
>
) : (
'Swap'
diff --git a/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/index.tsx b/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/index.tsx
index 1888b6d921..9ee5f5e376 100644
--- a/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/yield/containers/YieldWidget/index.tsx
@@ -27,7 +27,7 @@ import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
import { CoWAmmInlineBanner, SelectAPoolButton } from './elements'
import { usePoolsInfo } from '../../hooks/usePoolsInfo'
-import { useVampireAttackFirstTarget } from '../../hooks/useVampireAttack'
+import { useVampireAttack, useVampireAttackFirstTarget } from '../../hooks/useVampireAttack'
import { useYieldDerivedState } from '../../hooks/useYieldDerivedState'
import {
useYieldDeadlineState,
@@ -58,7 +58,7 @@ const YIELD_UNLOCK_SCREEN = {
}
export function YieldWidget() {
- const { chainId } = useWalletInfo()
+ const { chainId, account } = useWalletInfo()
const { showRecipient } = useYieldSettings()
const deadlineState = useYieldDeadlineState()
const recipientToggleState = useYieldRecipientToggleState()
@@ -69,6 +69,7 @@ export function YieldWidget() {
const widgetActions = useYieldWidgetActions()
const receiveAmountInfo = useReceiveAmountInfo()
const poolsInfo = usePoolsInfo()
+ const vampireAttackContext = useVampireAttack()
const vampireAttackTarget = useVampireAttackFirstTarget()
const {
@@ -100,6 +101,11 @@ export function YieldWidget() {
const inputApy = inputPoolState?.info.apy
const outputApy = outputPoolState?.info.apy
+ const isTradeContainAlternativePool =
+ inputCurrency instanceof LpToken &&
+ outputCurrency instanceof LpToken &&
+ inputCurrency.tokens.every((token) => outputCurrency.tokens.includes(token))
+
const inputCurrencyInfo: CurrencyInfo = {
field: Field.INPUT,
currency: inputCurrency,
@@ -113,8 +119,7 @@ export function YieldWidget() {
outputApy : true),
)}
@@ -136,7 +141,7 @@ export function YieldWidget() {
inputApy : true),
)}
@@ -161,7 +166,11 @@ export function YieldWidget() {
const rateInfoParams = useRateInfoParams(inputCurrencyInfo.amount, outputCurrencyInfo.amount)
const slots: TradeWidgetSlots = {
- topContent: ,
+ topContent: vampireAttackContext ? (
+
+ ) : !account ? (
+
+ ) : null,
selectTokenWidget: ,
settingsWidget: ,
bottomContent: useCallback(
diff --git a/apps/cowswap-frontend/src/modules/yield/state/lpTokensWithBalancesAtom.ts b/apps/cowswap-frontend/src/modules/yield/state/lpTokensWithBalancesAtom.ts
index 8c8a9593ba..2098983618 100644
--- a/apps/cowswap-frontend/src/modules/yield/state/lpTokensWithBalancesAtom.ts
+++ b/apps/cowswap-frontend/src/modules/yield/state/lpTokensWithBalancesAtom.ts
@@ -10,6 +10,6 @@ export type LpTokenWithBalance = {
type LpTokensWithBalancesState = { tokens: Record; count: 0 }
-export const LP_TOKENS_WITH_BALANCES_DEFAULT_STATE: LpTokensWithBalancesState = { tokens: {}, count: 0 }
+export const LP_TOKENS_WITH_BALANCES_DEFAULT_STATE: () => LpTokensWithBalancesState = () => ({ tokens: {}, count: 0 })
-export const lpTokensWithBalancesAtom = atom(LP_TOKENS_WITH_BALANCES_DEFAULT_STATE)
+export const lpTokensWithBalancesAtom = atom(LP_TOKENS_WITH_BALANCES_DEFAULT_STATE())
diff --git a/apps/cowswap-frontend/src/modules/yield/updaters/LpTokensWithBalancesUpdater/index.ts b/apps/cowswap-frontend/src/modules/yield/updaters/LpTokensWithBalancesUpdater/index.ts
index 9be3864707..00236675b9 100644
--- a/apps/cowswap-frontend/src/modules/yield/updaters/LpTokensWithBalancesUpdater/index.ts
+++ b/apps/cowswap-frontend/src/modules/yield/updaters/LpTokensWithBalancesUpdater/index.ts
@@ -3,12 +3,14 @@ import { useEffect } from 'react'
import { useTokensBalances } from '@cowprotocol/balances-and-allowances'
import { TokenListCategory, useAllLpTokens } from '@cowprotocol/tokens'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { LP_TOKENS_WITH_BALANCES_DEFAULT_STATE, lpTokensWithBalancesAtom } from '../../state/lpTokensWithBalancesAtom'
const LP_CATEGORY = [TokenListCategory.LP]
export function LpTokensWithBalancesUpdater() {
+ const { account } = useWalletInfo()
const lpTokens = useAllLpTokens(LP_CATEGORY)
const { values: balances } = useTokensBalances()
const setState = useSetAtom(lpTokensWithBalancesAtom)
@@ -16,23 +18,26 @@ export function LpTokensWithBalancesUpdater() {
useEffect(() => {
if (!lpTokens.length) return
- const state = lpTokens.reduce(
- (acc, token) => {
- const addressLower = token.address.toLowerCase()
- const balance = balances[addressLower]
+ const state = lpTokens.reduce((acc, token) => {
+ const addressLower = token.address.toLowerCase()
+ const balance = balances[addressLower]
- if (balance && !balance.isZero()) {
- acc.count++
- acc.tokens[addressLower] = { token, balance }
- }
+ if (balance && !balance.isZero()) {
+ acc.count++
+ acc.tokens[addressLower] = { token, balance }
+ }
- return acc
- },
- { ...LP_TOKENS_WITH_BALANCES_DEFAULT_STATE },
- )
+ return acc
+ }, LP_TOKENS_WITH_BALANCES_DEFAULT_STATE())
setState(state)
}, [setState, lpTokens, balances])
+ useEffect(() => {
+ if (!account) {
+ setState(LP_TOKENS_WITH_BALANCES_DEFAULT_STATE())
+ }
+ }, [account, setState])
+
return null
}
diff --git a/apps/cowswap-frontend/src/modules/yield/updaters/VampireAttackUpdater.tsx b/apps/cowswap-frontend/src/modules/yield/updaters/VampireAttackUpdater.tsx
index 3a64725f1e..06fcad7cff 100644
--- a/apps/cowswap-frontend/src/modules/yield/updaters/VampireAttackUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/yield/updaters/VampireAttackUpdater.tsx
@@ -3,6 +3,7 @@ import { useEffect, useMemo } from 'react'
import { LP_TOKEN_LIST_COW_AMM_ONLY, useAllLpTokens } from '@cowprotocol/tokens'
import { LpTokenProvider } from '@cowprotocol/types'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useLpTokensWithBalances, usePoolsInfo } from 'modules/yield/shared'
import { POOLS_AVERAGE_DATA_MOCK } from 'modules/yield/updaters/PoolsInfoUpdater/mockPoolInfo'
@@ -14,6 +15,7 @@ import { vampireAttackAtom } from '../state/vampireAttackAtom'
import { TokenWithAlternative, TokenWithSuperiorAlternative } from '../types'
export function VampireAttackUpdater(): null {
+ const { account } = useWalletInfo()
const { tokens: lpTokensWithBalances, count: lpTokensWithBalancesCount } = useLpTokensWithBalances()
const cowAmmLpTokens = useAllLpTokens(LP_TOKEN_LIST_COW_AMM_ONLY)
const poolsInfo = usePoolsInfo()
@@ -102,12 +104,12 @@ export function VampireAttackUpdater(): null {
})
useEffect(() => {
- if (cowAmmLpTokens.length === 0 || !areLpBalancesLoaded) {
+ if (!account || cowAmmLpTokens.length === 0 || !areLpBalancesLoaded) {
setVampireAttack(null)
} else {
setVampireAttack(context)
}
- }, [context, cowAmmLpTokens.length, areLpBalancesLoaded, setVampireAttack])
+ }, [account, context, cowAmmLpTokens.length, areLpBalancesLoaded, setVampireAttack])
return null
}
diff --git a/libs/balances-and-allowances/src/updaters/BalancesCacheUpdater.tsx b/libs/balances-and-allowances/src/updaters/BalancesCacheUpdater.tsx
index 724b5f6c9c..5ad2d697df 100644
--- a/libs/balances-and-allowances/src/updaters/BalancesCacheUpdater.tsx
+++ b/libs/balances-and-allowances/src/updaters/BalancesCacheUpdater.tsx
@@ -1,18 +1,23 @@
import { useAtom } from 'jotai/index'
-import { useEffect, useRef } from 'react'
+import { useEffect, useLayoutEffect, useRef } from 'react'
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { mapSupportedNetworks, SupportedChainId } from '@cowprotocol/cow-sdk'
import { BigNumber } from '@ethersproject/bignumber'
import { balancesAtom, balancesCacheAtom } from '../state/balancesAtom'
-export function BalancesCacheUpdater({ chainId }: { chainId: SupportedChainId }) {
+export function BalancesCacheUpdater({ chainId, account }: { chainId: SupportedChainId; account?: string }) {
const [balances, setBalances] = useAtom(balancesAtom)
const [balancesCache, setBalancesCache] = useAtom(balancesCacheAtom)
const areBalancesRestoredFromCacheRef = useRef(false)
// Persist into localStorage only non-zero balances
useEffect(() => {
+ if (!account) {
+ setBalancesCache(mapSupportedNetworks({}))
+ return
+ }
+
setBalancesCache((state) => {
const balancesValues = balances.values
@@ -50,12 +55,13 @@ export function BalancesCacheUpdater({ chainId }: { chainId: SupportedChainId })
},
}
})
- }, [chainId, balances.values, setBalancesCache, setBalances])
+ }, [chainId, account, balances.values, setBalancesCache])
// Restore balances from cache once
- useEffect(() => {
+ useLayoutEffect(() => {
const cache = balancesCache[chainId]
+ if (!account) return
if (areBalancesRestoredFromCacheRef.current) return
if (!cache) return
@@ -83,7 +89,7 @@ export function BalancesCacheUpdater({ chainId }: { chainId: SupportedChainId })
})
return
- }, [balancesCache, chainId, setBalances])
+ }, [balancesCache, chainId, account, setBalances])
return null
}