Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(farm): elastic #1247

Merged
merged 1 commit into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 123 additions & 85 deletions src/components/YieldPools/ProMMFarmGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CurrencyAmount, Fraction, Token } from '@kyberswap/ks-sdk-core'
import { CurrencyAmount, Token } from '@kyberswap/ks-sdk-core'
import { Pool, Position } from '@kyberswap/ks-sdk-elastic'
import { Trans, t } from '@lingui/macro'
import { BigNumber } from 'ethers'
import { rgba } from 'polished'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { Clock, Edit2, Info, Minus, Plus } from 'react-feather'
import { Clock, Edit2, Minus, Plus } from 'react-feather'
import { useMedia } from 'react-use'
import { Flex, Text } from 'rebass'
import styled from 'styled-components'
Expand All @@ -21,14 +21,13 @@ import Deposit from 'components/Icons/Deposit'
import Harvest from 'components/Icons/Harvest'
import Withdraw from 'components/Icons/Withdraw'
import InfoHelper from 'components/InfoHelper'
import Loader from 'components/Loader'
import Modal from 'components/Modal'
import { MouseoverTooltip, MouseoverTooltipDesktopOnly } from 'components/Tooltip'
import { ELASTIC_BASE_FEE_UNIT, ZERO_ADDRESS } from 'constants/index'
import { VERSION } from 'constants/v2'
import { useActiveWeb3React } from 'hooks'
import { useToken, useTokens } from 'hooks/Tokens'
import { useProAmmNFTPositionManagerContract, useProMMFarmContract } from 'hooks/useContract'
import { useProAmmNFTPositionManagerContract } from 'hooks/useContract'
import useParsedQueryString from 'hooks/useParsedQueryString'
import useTheme from 'hooks/useTheme'
import { Dots } from 'pages/Pool/styleds'
Expand Down Expand Up @@ -100,39 +99,39 @@ const Reward = ({ token: address, amount }: { token: string; amount?: BigNumber
)
}

const FeeTargetWrapper = styled.div<{ fullUnlock: boolean }>`
border-radius: 999px;
display: flex;
font-size: 12px;
background: ${({ theme, fullUnlock }) => (fullUnlock ? theme.primary : theme.subText)};
position: relative;
color: ${({ theme }) => theme.textReverse};
height: 20px;
align-items: center;
min-width: 120px;
`

const FeeArchive = styled.div<{ width: number }>`
width: ${({ width }) => `${width}%`};
height: 100%;
background: ${({ theme, width }) => (width === 100 ? theme.primary : theme.warning)};
border-radius: 999px;
`
const FeeText = styled.div`
position: absolute;
left: 50%;
transform: translateX(-50%);
`

const FeeTarget = ({ percent }: { percent: string }) => {
const p = Number(percent) * 100
return (
<FeeTargetWrapper fullUnlock={Number(percent) >= 1}>
<FeeArchive width={p}></FeeArchive>
<FeeText>{p.toFixed(2)}%</FeeText>
</FeeTargetWrapper>
)
}
// const FeeTargetWrapper = styled.div<{ fullUnlock: boolean }>`
// border-radius: 999px;
// display: flex;
// font-size: 12px;
// background: ${({ theme, fullUnlock }) => (fullUnlock ? theme.primary : theme.subText)};
// position: relative;
// color: ${({ theme }) => theme.textReverse};
// height: 20px;
// align-items: center;
// min-width: 120px;
// `

// const FeeArchive = styled.div<{ width: number }>`
// width: ${({ width }) => `${width}%`};
// height: 100%;
// background: ${({ theme, width }) => (width === 100 ? theme.primary : theme.warning)};
// border-radius: 999px;
// `
// const FeeText = styled.div`
// position: absolute;
// left: 50%;
// transform: translateX(-50%);
// `

// const FeeTarget = ({ percent }: { percent: string }) => {
// const p = Number(percent) * 100
// return (
// <FeeTargetWrapper fullUnlock={Number(percent) >= 1}>
// <FeeArchive width={p}></FeeArchive>
// <FeeText>{p.toFixed(2)}%</FeeText>
// </FeeTargetWrapper>
// )
// }

const Row = ({
isApprovedForAll,
Expand Down Expand Up @@ -229,39 +228,41 @@ const Row = ({
})
}, [position, farm.pid, onUpdateDepositedInfo])

const contract = useProMMFarmContract(fairlaunchAddress)

const [targetPercent, setTargetPercent] = useState('')
const [loading, setLoading] = useState(false)

useEffect(() => {
const getFeeTargetInfos = async () => {
if (!contract) return
setLoading(true)
const res = await Promise.all(
farm.userDepositedNFTs.map(async pos => {
const res = await contract.getRewardCalculationData(pos.tokenId, farm.pid)
return new Fraction(res.vestingVolume.toString(), BigNumber.from(1e12).toString())
}),
)

const totalLiquidity = farm.userDepositedNFTs.reduce(
(acc, cur) => acc.add(cur.stakedLiquidity),
BigNumber.from(0),
)
const targetLiqid = farm.userDepositedNFTs.reduce(
(acc, cur, index) => acc.add(res[index].multiply(cur.stakedLiquidity.toString())),
new Fraction(0, 1),
)

if (totalLiquidity.gt(0)) {
const targetPercent = targetLiqid.divide(totalLiquidity.toString())
setTargetPercent(targetPercent.toFixed(2))
}
setLoading(false)
}
getFeeTargetInfos()
}, [contract, farm])
// TODO: this is temporary hide target volume, an ad-hoc request from Product team. will enable soon if we have this kind of farm

// const contract = useProMMFarmContract(fairlaunchAddress)

// const [targetPercent, setTargetPercent] = useState('')
// const [loading, setLoading] = useState(false)

// useEffect(() => {
// const getFeeTargetInfos = async () => {
// if (!contract) return
// setLoading(true)
// const res = await Promise.all(
// farm.userDepositedNFTs.map(async pos => {
// const res = await contract.getRewardCalculationData(pos.tokenId, farm.pid)
// return new Fraction(res.vestingVolume.toString(), BigNumber.from(1e12).toString())
// }),
// )

// const totalLiquidity = farm.userDepositedNFTs.reduce(
// (acc, cur) => acc.add(cur.stakedLiquidity),
// BigNumber.from(0),
// )
// const targetLiqid = farm.userDepositedNFTs.reduce(
// (acc, cur, index) => acc.add(res[index].multiply(cur.stakedLiquidity.toString())),
// new Fraction(0, 1),
// )

// if (totalLiquidity.gt(0)) {
// const targetPercent = targetLiqid.divide(totalLiquidity.toString())
// setTargetPercent(targetPercent.toFixed(2))
// }
// setLoading(false)
// }
// getFeeTargetInfos()
// }, [contract, farm])

const [showTargetVolInfo, setShowTargetVolInfo] = useState(false)

Expand Down Expand Up @@ -328,13 +329,15 @@ const Row = ({
</Flex>
</Flex>

{/*
<InfoRow>
<Text color={theme.subText} display="flex" sx={{ gap: '4px' }} onClick={() => setShowTargetVolInfo(true)}>
<Trans>Target volume</Trans>
<Info size={12} />
</Text>
{farm.feeTarget.gt(0) ? loading ? <Loader /> : <FeeTarget percent={targetPercent} /> : '--'}
</InfoRow>
*/}

<InfoRow>
<Text color={theme.subText}>
Expand Down Expand Up @@ -370,6 +373,33 @@ const Row = ({
<Text>{getFormattedTimeFromSecond(farm.vestingDuration, true)}</Text>
</InfoRow>

<InfoRow>
<Text color={theme.subText}>
<Trans>Ending In</Trans>
<InfoHelper text={t`Once a farm has ended, you will continue to receive returns through LP Fees`} />
</Text>

<Flex flexDirection="column" alignItems="flex-end" justifyContent="center" sx={{ gap: '8px' }}>
{farm.startTime > currentTimestamp ? (
<>
<Text color={theme.subText} fontSize="12px">
<Trans>New phase will start in</Trans>
</Text>
{getFormattedTimeFromSecond(farm.startTime - currentTimestamp)}
</>
) : farm.endTime > currentTimestamp ? (
<>
<Text color={theme.subText} fontSize="12px">
<Trans>Current phase will end in</Trans>
</Text>
{getFormattedTimeFromSecond(farm.endTime - currentTimestamp)}
</>
) : (
<Trans>ENDED</Trans>
)}
</Flex>
</InfoRow>

<InfoRow>
<Text color={theme.subText}>
<Trans>My Deposit</Trans>
Expand Down Expand Up @@ -436,16 +466,6 @@ const Row = ({
<Text fontSize={14}>
{token0?.symbol} - {token1?.symbol}
</Text>

{farm.startTime > currentTimestamp && (
<MouseoverTooltip
text={'Starting In ' + getFormattedTimeFromSecond(farm.startTime - currentTimestamp)}
width="fit-content"
placement="top"
>
<Clock size={14} style={{ marginLeft: '6px' }} />
</MouseoverTooltip>
)}
</Flex>

<Flex
Expand All @@ -465,16 +485,34 @@ const Row = ({
</Flex>
</Flex>
</div>

{/*
{farm.feeTarget.gt(0) ? loading ? <Loader /> : <FeeTarget percent={targetPercent} /> : '--'}

<Text>{formatDollarAmount(tvl)}</Text>
*/}
<Text textAlign="right">{formatDollarAmount(tvl)}</Text>
<Text textAlign="end" color={theme.apr}>
{(farmAPR + poolAPY).toFixed(2)}%
<InfoHelper text={`${poolAPY.toFixed(2)}% Fee + ${farmAPR.toFixed(2)}% Rewards`} />
</Text>

<Text textAlign="end">{getFormattedTimeFromSecond(farm.vestingDuration, true)}</Text>
{/*<Text textAlign="end">{getFormattedTimeFromSecond(farm.vestingDuration, true)}</Text>*/}
<Flex flexDirection="column" alignItems="flex-end" justifyContent="center" sx={{ gap: '8px' }}>
{farm.startTime > currentTimestamp ? (
<>
<Text color={theme.subText} fontSize="12px">
<Trans>New phase will start in</Trans>
</Text>
{getFormattedTimeFromSecond(farm.startTime - currentTimestamp)}
</>
) : farm.endTime > currentTimestamp ? (
<>
<Text color={theme.subText} fontSize="12px">
<Trans>Current phase will end in</Trans>
</Text>
{getFormattedTimeFromSecond(farm.endTime - currentTimestamp)}
</>
) : (
<Trans>ENDED</Trans>
)}
</Flex>

<Text textAlign="right">{!!position?.amountUsd ? formatDollarAmount(position.amountUsd) : '--'}</Text>
<Flex flexDirection="column" alignItems="flex-end" sx={{ gap: '8px' }}>
Expand Down
39 changes: 29 additions & 10 deletions src/components/YieldPools/ProMMFarms.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Trans, t } from '@lingui/macro'
import { stringify } from 'querystring'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Info, Search } from 'react-feather'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Search } from 'react-feather'
import { useHistory, useLocation } from 'react-router-dom'
import { useMedia } from 'react-use'
import { Flex, Text } from 'rebass'

import HoverDropdown from 'components/HoverDropdown'
import InfoHelper from 'components/InfoHelper'
import LocalLoader from 'components/LocalLoader'
import Toggle from 'components/Toggle'
Expand All @@ -17,7 +16,7 @@ import useTheme from 'hooks/useTheme'
import { useBlockNumber } from 'state/application/hooks'
import { useGetProMMFarms, useProMMFarms } from 'state/farms/promm/hooks'
import { ProMMFarm } from 'state/farms/promm/types'
import { ExternalLink, StyledInternalLink } from 'theme'
import { StyledInternalLink } from 'theme'

import ProMMFarmGroup from './ProMMFarmGroup'
import { DepositModal, StakeUnstakeModal } from './ProMMFarmModals'
Expand Down Expand Up @@ -82,7 +81,11 @@ function ProMMFarms({ active }: { active: boolean }) {
const filterSearchText = search
? farm.token0.toLowerCase().includes(search) ||
farm.token1.toLowerCase().includes(search) ||
farm.poolAddress.toLowerCase() === search
farm.poolAddress.toLowerCase() === search ||
farm?.token0Info?.symbol?.toLowerCase().includes(search) ||
farm?.token1Info?.symbol?.toLowerCase().includes(search) ||
farm?.token0Info?.name?.toLowerCase().includes(search) ||
farm?.token1Info?.name?.toLowerCase().includes(search)
: true

let filterStaked = true
Expand Down Expand Up @@ -165,6 +168,21 @@ function ProMMFarms({ active }: { active: boolean }) {
</Text>
)}

{qs.type === 'active' && qs.tab !== VERSION.CLASSIC && (
<>
<Text fontSize={12} fontWeight="500" marginBottom="0.375rem">
<Trans>Farms will run in multiple phases.</Trans>
</Text>
<Text fontStyle="italic" fontSize={12} marginBottom="1rem" color={theme.subText}>
<Trans>
Once the current phase ends, you can harvest your rewards from the farm in the{' '}
<StyledInternalLink to="/farms?type=ended">Ended</StyledInternalLink> tab. To continue earning rewards in
the new phase, you must restake your NFT position into the active farm.
</Trans>
</Text>
</>
)}

{above1000 && (
<ProMMFarmTableHeader>
<Flex grid-area="token_pairs" alignItems="center" justifyContent="flex-start">
Expand All @@ -173,7 +191,7 @@ function ProMMFarms({ active }: { active: boolean }) {
</ClickableText>
</Flex>

<Flex grid-area="pool_fee" alignItems="center" justifyContent="flex-start">
{/* <Flex grid-area="pool_fee" alignItems="center" justifyContent="flex-start">
<HoverDropdown
hideIcon
padding="8px 0"
Expand Down Expand Up @@ -201,8 +219,9 @@ function ProMMFarms({ active }: { active: boolean }) {
}
/>
</Flex>
*/}

<Flex grid-area="liq" alignItems="center" justifyContent="flex-center">
<Flex grid-area="liq" alignItems="center" justifyContent="flex-end">
<ClickableText>
<Trans>Staked TVL</Trans>
</ClickableText>
Expand All @@ -221,11 +240,11 @@ function ProMMFarms({ active }: { active: boolean }) {
/>
</Flex>

<Flex grid-area="vesting_duration" alignItems="center" justifyContent="flex-end">
<Flex grid-area="end" alignItems="center" justifyContent="flex-end">
<ClickableText>
<Trans>Vesting</Trans>
<Trans>Ending In</Trans>
</ClickableText>
<InfoHelper text={t`After harvesting, your rewards will unlock linearly over the indicated time period`} />
<InfoHelper text={t`Once a farm has ended, you will continue to receive returns through LP Fees`} />
</Flex>

<Flex grid-area="staked_balance" alignItems="center" justifyContent="flex-end">
Expand Down
Loading