Skip to content

Commit

Permalink
feat: add ifo for solv (#11116)
Browse files Browse the repository at this point in the history
<!--
Before opening a pull request, please read the [contributing
guidelines](https://github.com/pancakeswap/pancake-frontend/blob/develop/CONTRIBUTING.md)
first
-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on adding support for the `SOLV` token launch
(IFO) on PancakeSwap, including updates to configuration, new
components, and enhancements in the vesting logic.

### Detailed summary
- Added `SOLV` token launch configuration in
`packages/ifos/src/constants/ifos/bsc.ts`.
- Introduced `AdSolv` component for promotional ads.
- Updated `Claim` component to include vesting status.
- Enhanced vesting logic to track user claimable amounts.
- Modified various hooks and components to integrate `SOLV` IFO data.
- Updated localization strings for `SOLV` IFO.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your
question}`

<!-- end pr-codex -->
  • Loading branch information
chef-ryan authored Jan 14, 2025
1 parent b9d7bf0 commit 58ab27c
Show file tree
Hide file tree
Showing 27 changed files with 756 additions and 398 deletions.
3 changes: 0 additions & 3 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
"not op_mini all"
]
},
"engines": {
"node": ">=16.0.0"
},
"dependencies": {
"@binance/w3w-utils": "1.1.4",
"@binance/w3w-wagmi-connector-v2": "^1.2.3",
Expand Down
33 changes: 33 additions & 0 deletions apps/web/src/components/AdPanel/Ads/AdSolv.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useTranslation } from '@pancakeswap/localization'
import { BodyText } from '../BodyText'
import { AdButton } from '../Button'
import { AdCard } from '../Card'
import { Countdown } from '../Countdown'
import { AdPlayerProps } from '../types'
import { getImageUrl } from '../utils'

export const AdSolv = (props: AdPlayerProps) => {
const { t } = useTranslation()

return (
<AdCard imageUrl={getImageUrl('solv')} {...props}>
<BodyText mb="8px">
{t('%token% IFO starts in', {
token: 'SOLV',
})}
</BodyText>

<Countdown
targetTime={new Date('2025-01-16T10:00:00Z').getTime() / 1000}
subtleColor="rgba(0,0,0,.6)"
background="linear-gradient(180deg, #FCC631 0%, #FF9D00 100%)"
color="black"
mb="8px"
/>

<AdButton variant="text" isExternalLink href="https://pancakeswap.finance/ifo">
{t('Get Started')}
</AdButton>
</AdCard>
)
}
27 changes: 4 additions & 23 deletions apps/web/src/components/AdPanel/config.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useMatchBreakpoints } from '@pancakeswap/uikit'
import { useMemo } from 'react'
import { AdCakeStaking } from './Ads/AdCakeStaking'
import { AdOptionsTrading } from './Ads/AdOptionsTrading'
import { AdPCSX } from './Ads/AdPCSX'
import { AdRocker } from './Ads/AdRocker'
import { AdSolv } from './Ads/AdSolv'
import { AdSpringboard } from './Ads/AdSpringboard'
import { AdTradingCompetitionBfg, AdTradingCompetitionVinu } from './Ads/AdTradingCompetition'
import { AdTradingCompetitionVinu } from './Ads/AdTradingCompetition'
import { ExpandableAd } from './Expandable/ExpandableAd'
import { shouldRenderOnPages } from './renderConditions'

Expand Down Expand Up @@ -45,18 +44,9 @@ export const useAdConfig = () => {
component: <AdTradingCompetitionVinu />,
},
{
id: 'ad-bfg-tc',
component: <AdTradingCompetitionBfg />,
id: 'ad-ifo-solv',
component: <AdSolv />,
},

// {
// id: 'ad-mev',
// component: <AdMevProtection />,
// },
// {
// id: 'prediction-telegram-bot',
// component: <AdTelegramBot />,
// },
{
id: 'pcsx',
component: <AdPCSX />,
Expand All @@ -65,15 +55,6 @@ export const useAdConfig = () => {
id: 'cake-staking',
component: <AdCakeStaking />,
},
{
id: 'clamm-options-trading',
component: <AdOptionsTrading />,
},

{
id: 'rocker-meme-career',
component: <AdRocker />,
},
],
[shouldRenderOnPage],
)
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/Menu/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ const config: (
],
items: [
{
status: { text: t('New'), color: 'success' },
label: t('Springboard'),
href: 'https://springboard.pancakeswap.finance',
type: DropdownMenuItemType.EXTERNAL_LINK,
Expand Down Expand Up @@ -201,6 +200,7 @@ const config: (
label: t('IFO'),
href: '/ifo',
image: '/images/ifos/ifo-bunny.png',
status: { text: t('SOON'), color: 'warning' },
overrideSubNavItems: [
{
label: t('Latest'),
Expand Down
62 changes: 62 additions & 0 deletions apps/web/src/components/PhishingWarningBanner/SolvStrip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useTranslation } from '@pancakeswap/localization'
import { Box, Link, Text } from '@pancakeswap/uikit'
import { VerticalDivider } from '@pancakeswap/widgets-internal'

const TextHighlight = ({ text, highlights }: { text: string; highlights: string[] }) => {
const prts = text.split(new RegExp(`(${highlights.join('|')})`, 'g'))
return prts.map((prt, i) => {
const key = `${prt}-${i}`
if (highlights.includes(prt)) {
return (
<Text bold as="span" color="#FCC631" fontSize={['12px', '12px', '14px']} key={key}>
{prt}
</Text>
)
}
return (
<Text bold as="span" color="#FFFFFF" fontSize={['12px', '12px', '14px']} key={key}>
{prt}
</Text>
)
})
}
export const SolvStrip = () => {
const { t } = useTranslation()

return (
<Box mr={['6px']}>
<TextHighlight
text={t('Join the SOLV Token Launch (IFO) on BNB Chain PancakeSwap')}
highlights={['SOLV', 'PancakeSwap']}
/>{' '}
<Link
external
display="inline !important"
fontSize={['12px', '12px', '14px']}
href="https://pancakeswap.finance/ifo"
>
{t('Join Now')}
</Link>
<VerticalDivider
bg="#53DEE9"
style={{
display: 'inline-block',
verticalAlign: 'middle',
height: '18px',
opacity: 0.4,
width: '1px',
marginLeft: '0px',
marginRight: '8px',
}}
/>
<Link
external
display="inline !important"
fontSize={['12px', '12px', '14px']}
href="https://forum.pancakeswap.finance/t/solv-ifo-discussion-thread/993"
>
{t('Learn More')}
</Link>
</Box>
)
}
15 changes: 8 additions & 7 deletions apps/web/src/components/PhishingWarningBanner/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import 'swiper/css/effect-fade'
import { ASSET_CDN } from 'config/constants/endpoints'
import { Countdown } from './Countdown'

import { SolvStrip } from './SolvStrip'
import { Step1 } from './Step1'
import { Step2 } from './Step2'
import { Step3 } from './Step3'
import { TradingCompetitionBfg, TradingCompetitionVinu } from './TradingCompetition'
import { TradingCompetitionVinu } from './TradingCompetition'

const Container = styled(Flex).withConfig({ shouldForwardProp: (prop) => !['$background'].includes(prop) })<{
$background?: string
Expand Down Expand Up @@ -99,6 +100,12 @@ type BannerConfig = {
}

const CONFIG: BannerConfig[] = [
{
component: SolvStrip,
stripeImage: `${ASSET_CDN}/web/phishing-warning/solv.png?v=1`,
stripeImageWidth: '92px',
stripeImageAlt: 'SOLV IFO',
},
{
component: Step1,
stripeImage: `${ASSET_CDN}/web/phishing-warning/phishing-warning-bunny-1.png`,
Expand All @@ -117,12 +124,6 @@ const CONFIG: BannerConfig[] = [
stripeImageWidth: '92px',
stripeImageAlt: 'PCSX',
},
{
component: TradingCompetitionBfg,
stripeImage: `${ASSET_CDN}/web/promotions/bfg_competition.png`,
stripeImageWidth: '92px',
stripeImageAlt: 'bfg_competition',
},
{
component: TradingCompetitionVinu,
stripeImage: `${ASSET_CDN}/web/promotions/vinu_competition.png`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { CAKE } from '@pancakeswap/tokens'
import { Box, Flex, IfoSkeletonCardDetails, Skeleton, Text, TooltipText, useTooltip } from '@pancakeswap/uikit'
import { BIG_ONE_HUNDRED } from '@pancakeswap/utils/bigNumber'
import { formatNumber, getBalanceNumber } from '@pancakeswap/utils/formatBalance'
import { DAY_IN_SECONDS } from '@pancakeswap/utils/getTimePeriods'
import BigNumber from 'bignumber.js'
import { useStablecoinPrice } from 'hooks/useStablecoinPrice'
import { ReactNode, useMemo } from 'react'
Expand Down Expand Up @@ -141,6 +140,23 @@ const MaxTokenEntry = ({
)
}

const useTimeUntilDiffTime = (diffTime: number): string => {
const { t } = useTranslation()
if (diffTime <= 0) {
return t('The time has already passed.')
}

const diffInHours = Math.floor(diffTime / (60 * 60))
const diffInDays = Math.floor(diffInHours / 24)
const unitDay = t('day(s)')
const unitHour = t('hour(s)')

if (diffInDays >= 1) {
return `${diffInDays} ${unitDay}`
}
return `${diffInHours} ${unitHour}`
}

const IfoCardDetails: React.FC<React.PropsWithChildren<IfoCardDetailsProps>> = ({
isEligible,
poolId,
Expand Down Expand Up @@ -220,7 +236,8 @@ const IfoCardDetails: React.FC<React.PropsWithChildren<IfoCardDetailsProps>> = (
)

const durationInSeconds = ifo.version >= 3.2 ? poolCharacteristic?.vestingInformation?.duration ?? 0 : 0
const vestingDays = Math.ceil(durationInSeconds / DAY_IN_SECONDS)
// const vestingDays = Math.ceil(durationInSeconds / DAY_IN_SECONDS)
const vestingCountdown = useTimeUntilDiffTime(durationInSeconds)

/* Format end */
const renderBasedOnIfoStatus = () => {
Expand Down Expand Up @@ -276,9 +293,9 @@ const IfoCardDetails: React.FC<React.PropsWithChildren<IfoCardDetailsProps>> = (
/>
<FooterEntry
label={t('Vesting schedule:')}
value={`${vestingDays} days`}
tooltipContent={t('The vested tokens will be released linearly over a period of %days% days.', {
days: vestingDays,
value={vestingCountdown}
tooltipContent={t('The vested tokens will be released linearly over a period of %countdown%.', {
countdown: vestingCountdown,
})}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Ifo, PoolIds, cakeBnbLpToken } from '@pancakeswap/ifos'
import { useTranslation } from '@pancakeswap/localization'
import { Token } from '@pancakeswap/sdk'
import { ChainId, Token } from '@pancakeswap/sdk'
import { bscTokens } from '@pancakeswap/tokens'
import {
AutoRenewIcon,
Expand Down Expand Up @@ -229,9 +229,9 @@ const IfoCardTokens: React.FC<React.PropsWithChildren<IfoCardTokensProps>> = ({
hasProfile
) {
// If Cross-Chain IFO
// if (ifo.chainId !== ChainId.BSC) {
message = <CrossChainVeCakeTips ifoChainId={ifo.chainId} />
// }
if (ifo.chainId !== ChainId.BSC) {
message = <CrossChainVeCakeTips ifoChainId={ifo.chainId} />
}
// Phase this out later, as it applies at the same time
// else message = <ICakeTips ifoId={ifo.id} ifoChainId={ifo.chainId} ifoAddress={ifo.address} />
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface Props {
claimableAmount: string
isVestingInitialized: boolean
fetchUserVestingData: () => void
enabled: boolean
}

const ClaimButton: React.FC<React.PropsWithChildren<Props>> = ({
Expand All @@ -25,6 +26,7 @@ const ClaimButton: React.FC<React.PropsWithChildren<Props>> = ({
claimableAmount,
isVestingInitialized,
fetchUserVestingData,
enabled,
}) => {
const { account, chain } = useWeb3React()
const { t } = useTranslation()
Expand Down Expand Up @@ -85,10 +87,10 @@ const ClaimButton: React.FC<React.PropsWithChildren<Props>> = ({
width="100%"
onClick={handleClaim}
isLoading={isPending}
disabled={isReady}
disabled={isReady && !enabled}
endIcon={isPending ? <AutoRenewIcon spin color="currentColor" /> : null}
>
{t('Claim %symbol%', { symbol: token.symbol })}
{t('Claim')}
</Button>
)
}
Expand Down
Loading

0 comments on commit 58ab27c

Please sign in to comment.