Skip to content

Commit

Permalink
feat: add poolinfo element
Browse files Browse the repository at this point in the history
  • Loading branch information
fairlighteth committed Oct 15, 2024
1 parent 33918c4 commit b0bb426
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react'
import { useCallback, useMemo, useRef } from 'react'

import ICON_ARROW from '@cowprotocol/assets/cow-swap/arrow.svg'
Expand All @@ -15,10 +16,14 @@ import { upToSmall, useMediaQuery } from 'legacy/hooks/useMediaQuery'
import { useIsDarkMode } from 'legacy/state/user/hooks'

import { ArrowBackground } from './arrowBackground'
import { LpToken, StateKey } from './dummyData'
import { LpToken, StateKey, dummyData, lpTokenConfig } from './dummyData'
import * as styledEl from './styled'

import { BannerLocation, DEMO_DROPDOWN_OPTIONS } from './index'
import { TokenLogo } from '../../../../../../libs/tokens/src/pure/TokenLogo'
import { USDC, WBTC } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { DummyDataType, TwoLpScenario } from './dummyData'

const lpTokenIcons: Record<LpToken, string> = {
[LpToken.UniswapV2]: ICON_UNISWAP,
Expand All @@ -35,12 +40,28 @@ interface CoWAmmBannerContentProps {
isDemo: boolean
selectedState: StateKey
setSelectedState: (state: StateKey) => void
dummyData: Record<StateKey, { apr: number; comparison: string }>
lpTokenConfig: Record<StateKey, LpToken[]>
dummyData: typeof dummyData
lpTokenConfig: typeof lpTokenConfig
onCtaClick: () => void
onClose: () => void
}

function isTwoLpScenario(scenario: DummyDataType[keyof DummyDataType]): scenario is TwoLpScenario {
return 'uniV2Apr' in scenario && 'sushiApr' in scenario
}

const renderTextfit = (
content: React.ReactNode,
mode: 'single' | 'multi',
minFontSize: number,
maxFontSize: number,
key: string,
) => (
<Textfit key={key} mode={mode} forceSingleModeWidth={false} min={minFontSize} max={maxFontSize}>
{content}
</Textfit>
)

export function CoWAmmBannerContent({
id,
title,
Expand Down Expand Up @@ -72,26 +93,104 @@ export function CoWAmmBannerContent({
}
}, [])

const { apr, comparison } = dummyData[selectedState]
const { apr } = dummyData[selectedState]

const aprMessage = useMemo(() => `+${apr.toFixed(1)}%`, [apr])

const comparisonMessage = useMemo(() => {
if (selectedState === 'noLp') {
return `yield over the average UNI-V2 pool`
const currentData = dummyData[selectedState]

if (!currentData) {
return 'Invalid state selected'
}
const prefix = ['twoLps', 'threeLps'].includes(selectedState)
? 'Get higher average APR than'
: 'Get higher APR than'
return `${prefix} ${comparison}`
}, [selectedState, comparison])

const renderPoolInfo = (poolName: string) => (
<styledEl.PoolInfo
flow={location === BannerLocation.TokenSelector ? 'row' : 'column'}
align={location === BannerLocation.TokenSelector ? 'center' : 'flex-start'}
bgColor={
location === BannerLocation.TokenSelector ? `var(${UI.COLOR_COWAMM_DARK_GREEN_OPACITY_15})` : undefined
}
color={location === BannerLocation.TokenSelector ? `var(${UI.COLOR_COWAMM_DARK_GREEN})` : undefined}
tokenBorderColor={location === BannerLocation.TokenSelector ? `var(${UI.COLOR_COWAMM_LIGHT_GREEN})` : undefined}
>
higher APR available for your {poolName} pool:
<i>
<div>
<TokenLogo token={WBTC} /> <TokenLogo token={USDC[SupportedChainId.MAINNET]} />
</div>
<span>WBTC-USDC</span>
</i>
</styledEl.PoolInfo>
)

if (isTwoLpScenario(currentData)) {
if (selectedState === 'twoLpsMixed') {
return renderPoolInfo('UNI-V2')
} else if (selectedState === 'twoLpsBothSuperior') {
const { uniV2Apr, sushiApr } = currentData
const higherAprPool = uniV2Apr > sushiApr ? 'UNI-V2' : 'SushiSwap'
return renderPoolInfo(higherAprPool)
}
}

if (selectedState === 'uniV2Superior') {
return renderPoolInfo('UNI-V2')
}

if (currentData.hasCoWAmmPool) {
return `yield over average ${currentData.comparison} pool`
} else {
const tokens = lpTokenConfig[selectedState]
if (tokens.length > 1) {
const tokenNames = tokens
.map((token) => {
switch (token) {
case LpToken.UniswapV2:
return 'UNI-V2'
case LpToken.Sushiswap:
return 'Sushi'
case LpToken.PancakeSwap:
return 'PancakeSwap'
case LpToken.Curve:
return 'Curve'
default:
return ''
}
})
.filter(Boolean)

return `yield over average ${tokenNames.join(', ')} pool${tokenNames.length > 1 ? 's' : ''}`
} else {
return `yield over average UNI-V2 pool`
}
}
}, [selectedState, lpTokenConfig])

const lpEmblems = useMemo(() => {
const tokens = lpTokenConfig[selectedState]
const totalItems = tokens.length

if (totalItems === 0) {
return null
// Fallback to UniswapV2 emblem if no LP tokens
return (
<styledEl.LpEmblems>
<styledEl.LpEmblemItem key={LpToken.UniswapV2} totalItems={1} index={0}>
<SVG src={lpTokenIcons[LpToken.UniswapV2]} />
</styledEl.LpEmblemItem>
<styledEl.EmblemArrow>
<SVG src={ICON_ARROW} />
</styledEl.EmblemArrow>
<styledEl.CoWAMMEmblemItem>
<ProductLogo
height={'100%'}
overrideColor={`var(${UI.COLOR_COWAMM_DARK_GREEN})`}
variant={ProductVariant.CowAmm}
logoIconOnly
/>
</styledEl.CoWAMMEmblemItem>
</styledEl.LpEmblems>
)
}

return (
Expand All @@ -116,27 +215,22 @@ export function CoWAmmBannerContent({
</styledEl.CoWAMMEmblemItem>
</styledEl.LpEmblems>
)
}, [selectedState, lpTokenConfig])

const renderProductLogo = (color: string) => (
<ProductLogo height={20} overrideColor={`var(${color})`} variant={ProductVariant.CowAmm} logoIconOnly />
)
}, [selectedState, lpTokenConfig, lpTokenIcons])

const renderStarIcon = (props: any) => (
<styledEl.StarIcon {...props}>
<SVG src={ICON_STAR} />
</styledEl.StarIcon>
const renderProductLogo = useCallback(
(color: string) => (
<ProductLogo height={20} overrideColor={`var(${color})`} variant={ProductVariant.CowAmm} logoIconOnly />
),
[],
)

const renderTextfit = (
content: React.ReactNode,
mode: 'single' | 'multi',
minFontSize: number,
maxFontSize: number,
) => (
<Textfit mode={mode} forceSingleModeWidth={false} min={minFontSize} max={maxFontSize}>
{content}
</Textfit>
const renderStarIcon = useCallback(
(props: any) => (
<styledEl.StarIcon {...props}>
<SVG src={ICON_STAR} />
</styledEl.StarIcon>
),
[],
)

const renderTokenSelectorContent = () => (
Expand All @@ -159,20 +253,23 @@ export function CoWAmmBannerContent({
bgColor={'transparent'}
borderColor={`var(${isDarkMode ? UI.COLOR_COWAMM_LIGHT_GREEN_OPACITY_30 : UI.COLOR_COWAMM_DARK_GREEN_OPACITY_30})`}
borderWidth={2}
padding={'14px'}
padding={'10px'}
gap={'14px'}
height={'78px'}
height={'max-content'}
>
{renderStarIcon({ size: 26, top: -16, right: 80, color: `var(${UI.COLOR_COWAMM_LIGHTER_GREEN})` })}
<h3>{renderTextfit(aprMessage, 'single', 45, 48)}</h3>
<span>{renderTextfit(comparisonMessage, 'multi', 12, 21)}</span>
<h3>{renderTextfit(aprMessage, 'single', 24, 48, `apr-${selectedState}`)}</h3>
<span>
{renderTextfit(comparisonMessage, 'multi', 12, isMobile ? 18 : 21, `comparison-${selectedState}`)}
</span>
{renderStarIcon({ size: 16, bottom: 3, right: 20, color: `var(${UI.COLOR_COWAMM_LIGHTER_GREEN})` })}
</styledEl.Card>
<styledEl.CTAButton
onClick={onCtaClick}
onMouseEnter={handleCTAMouseEnter}
onMouseLeave={handleCTAMouseLeave}
size={38}
fontSizeMobile={18}
fontSize={18}
bgColor={isDarkMode ? `var(${UI.COLOR_COWAMM_LIGHT_GREEN})` : `var(${UI.COLOR_COWAMM_DARK_GREEN})`}
bgHoverColor={isDarkMode ? `var(${UI.COLOR_COWAMM_LIGHTER_GREEN})` : `var(${UI.COLOR_COWAMM_GREEN})`}
Expand All @@ -184,45 +281,50 @@ export function CoWAmmBannerContent({
</styledEl.TokenSelectorWrapper>
)

const renderGlobalContent = () => (
<styledEl.BannerWrapper>
<styledEl.CloseButton size={24} onClick={onClose} />
<styledEl.Title>
{renderProductLogo(UI.COLOR_COWAMM_LIGHT_GREEN)}
<span>{title}</span>
</styledEl.Title>
<styledEl.Card bgColor={`var(${UI.COLOR_COWAMM_BLUE})`}>
{renderStarIcon({ size: 36, top: -17, right: 80 })}
<h3>{renderTextfit(aprMessage, 'single', 80, 80)}</h3>
<span>{renderTextfit(comparisonMessage, 'multi', 10, 28)}</span>
{renderStarIcon({ size: 26, bottom: -10, right: 20 })}
</styledEl.Card>

{!isMobile && (
<styledEl.Card bgColor={`var(${UI.COLOR_COWAMM_GREEN})`} color={`var(${UI.COLOR_COWAMM_LIGHT_GREEN})`}>
const renderGlobalContent = () => {
return (
<styledEl.BannerWrapper>
<styledEl.CloseButton size={24} onClick={onClose} />
<styledEl.Title>
{renderProductLogo(UI.COLOR_COWAMM_LIGHT_GREEN)}
<span>{title}</span>
</styledEl.Title>
<styledEl.Card bgColor={`var(${UI.COLOR_COWAMM_BLUE})`} color={`var(${UI.COLOR_COWAMM_DARK_BLUE})`}>
{renderStarIcon({ size: 36, top: -17, right: 80 })}
<h3>{renderTextfit(aprMessage, 'single', isMobile ? 40 : 80, isMobile ? 50 : 80, `apr-${selectedState}`)}</h3>
<span>
{renderTextfit(
<>
One-click convert, <strong>boost yield</strong>
</>,
'multi',
10,
30,
)}
{renderTextfit(comparisonMessage, 'multi', 10, isMobile ? 21 : 28, `comparison-${selectedState}`)}
</span>
{lpEmblems}
{renderStarIcon({ size: 26, bottom: -10, right: 20 })}
</styledEl.Card>
)}

<styledEl.CTAButton onClick={onCtaClick} onMouseEnter={handleCTAMouseEnter} onMouseLeave={handleCTAMouseLeave}>
{ctaText}
</styledEl.CTAButton>
{!isMobile && (
<styledEl.Card bgColor={`var(${UI.COLOR_COWAMM_GREEN})`} color={`var(${UI.COLOR_COWAMM_LIGHT_GREEN})`}>
<span>
{renderTextfit(
<>
One-click convert, <strong>boost yield</strong>
</>,
'multi',
10,
30,
`boost-yield-${selectedState}`,
)}
</span>
{lpEmblems}
</styledEl.Card>
)}

<styledEl.SecondaryLink href={'https://cow.fi/'}>Pool analytics ↗</styledEl.SecondaryLink>
<styledEl.CTAButton onClick={onCtaClick} onMouseEnter={handleCTAMouseEnter} onMouseLeave={handleCTAMouseLeave}>
{ctaText}
</styledEl.CTAButton>

<ArrowBackground ref={arrowBackgroundRef} />
</styledEl.BannerWrapper>
)
<styledEl.SecondaryLink href={'https://cow.fi/'}>Pool analytics ↗</styledEl.SecondaryLink>

<ArrowBackground ref={arrowBackgroundRef} />
</styledEl.BannerWrapper>
)
}

const renderDemoDropdown = () => (
<styledEl.DEMO_DROPDOWN value={selectedState} onChange={(e) => setSelectedState(e.target.value as StateKey)}>
Expand Down
Loading

0 comments on commit b0bb426

Please sign in to comment.