Skip to content

Commit

Permalink
feat(EX-2693): enable bsc, arb, avax chain for zap earn (#2592)
Browse files Browse the repository at this point in the history
* feat: enable bsc chain for zap earn

* feat: enable arb and ava chain for zap earn

* feat: add user positions filters to url query string

* fix: native token to claim

* fix: issues when owner of nft position is not wallet address (due to farming)

* fix(earn-position): reset dex filter if chain does not support that dex

* fix: price changed

* fix: add avax native address

* fix: format overflow price

* fix: pancake to pancake swap

* chore: refactor file code

* chore: fix API endpoint

* fix: position detail responsive

* fix: position detail responsive

* fix: fix header liquidity widget in small screen

* fix: some ui

* chore: prepare to release

* chore: remove callstatic when call read func from contract

---------

Co-authored-by: Nguyen Van Viet <[email protected]>
  • Loading branch information
tienkane and viet-nv authored Feb 18, 2025
1 parent ac9cc79 commit 5b399af
Show file tree
Hide file tree
Showing 15 changed files with 148 additions and 91 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"@kyberswap/ks-sdk-classic": "^1.0.3",
"@kyberswap/ks-sdk-core": "1.1.8",
"@kyberswap/ks-sdk-elastic": "^1.1.2",
"@kyberswap/liquidity-widgets": "1.1.12",
"@kyberswap/liquidity-widgets": "1.1.17",
"@kyberswap/zap-migration-widgets": "1.0.7",
"@kyberswap/oauth2": "1.0.2",
"@lingui/macro": "^4.6.0",
Expand Down
16 changes: 8 additions & 8 deletions src/pages/Earns/PositionDetail/LeftSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@ import InfoHelper from 'components/InfoHelper'
import Loader from 'components/Loader'
import NonfungiblePositionManagerABI from 'constants/abis/uniswapv3NftManagerContract.json'
import { NETWORKS_INFO } from 'constants/networks'
import { useActiveWeb3React } from 'hooks'
import { useReadingContract } from 'hooks/useContract'
import useTheme from 'hooks/useTheme'
import { useAllTransactions } from 'state/transactions/hooks'
import { formatDisplayNumber } from 'utils/numbers'

import { ParsedPosition } from '.'
import { DexImage } from '../UserPositions/styles'
import ClaimFeeModal, { isNativeToken } from '../components/ClaimFeeModal'
import { NFT_MANAGER_CONTRACT } from '../constants'
import { formatAprNumber } from '../utils'
import ClaimFeeModal, { isNativeToken } from './ClaimFeeModal'
import {
InfoLeftColumn,
InfoRight,
Expand Down Expand Up @@ -53,7 +52,6 @@ const LeftSection = ({ position }: { position: ParsedPosition }) => {
const [feeInfo, setFeeInfo] = useState<FeeInfo | null>(null)

const allTransactions = useAllTransactions(true)
const { account } = useActiveWeb3React()

const { data: historyData } = usePositionHistoryQuery({
chainId: position.chainId,
Expand Down Expand Up @@ -86,15 +84,16 @@ const LeftSection = ({ position }: { position: ParsedPosition }) => {

const handleFetchUnclaimedFee = useCallback(async () => {
if (!contract) return
const owner = await contract.ownerOf(position.id)
const maxUnit = '0x' + (2n ** 128n - 1n).toString(16)
const results = await contract.callStatic.collect(
{
tokenId: position.id,
recipient: account,
recipient: owner,
amount0Max: maxUnit,
amount1Max: maxUnit,
},
{ from: account },
{ from: owner },
)
const balance0 = results.amount0.toString()
const balance1 = results.amount1.toString()
Expand All @@ -116,7 +115,6 @@ const LeftSection = ({ position }: { position: ParsedPosition }) => {
totalValue: parseFloat(amount0) * position.token0Price + parseFloat(amount1) * position.token1Price,
})
}, [
account,
contract,
position.chainId,
position.id,
Expand Down Expand Up @@ -150,6 +148,8 @@ const LeftSection = ({ position }: { position: ParsedPosition }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allTransactions])

const nativeToken = NETWORKS_INFO[position.chainId as keyof typeof NETWORKS_INFO].nativeToken

return (
<InfoLeftColumn>
{openClaimFeeModal && feeInfo && (
Expand Down Expand Up @@ -265,7 +265,7 @@ const LeftSection = ({ position }: { position: ParsedPosition }) => {
<div>
<Flex alignItems={'center'} sx={{ gap: '6px' }} marginBottom={1}>
<Text>{formatDisplayNumber(feeInfo?.amount0, { significantDigits: 4 })}</Text>
<Text>{isToken0Native ? 'ETH' : position.token0Symbol}</Text>
<Text>{isToken0Native ? nativeToken.symbol : position.token0Symbol}</Text>
<Text fontSize={14} color={theme.subText}>
{formatDisplayNumber(feeInfo?.value0, {
style: 'currency',
Expand All @@ -275,7 +275,7 @@ const LeftSection = ({ position }: { position: ParsedPosition }) => {
</Flex>
<Flex alignItems={'center'} sx={{ gap: '6px' }}>
<Text>{formatDisplayNumber(feeInfo?.amount1, { significantDigits: 4 })}</Text>
<Text>{isToken1Native ? 'ETH' : position.token1Symbol}</Text>
<Text>{isToken1Native ? nativeToken.symbol : position.token1Symbol}</Text>
<Text fontSize={14} color={theme.subText}>
{formatDisplayNumber(feeInfo?.value1, {
style: 'currency',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const ChartWrapper = styled.div`
align-items: center;
justify-content: center;
width: 76%;
${({ theme }) => theme.mediaWidth.upToSmall`
width: 100%;
`}
`

export default function LiquidityChartRangeInput({
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Earns/PositionDetail/RightSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const RightSection = ({ position }: { position: ParsedPosition }) => {
return (
<InfoRightColumn>
<InfoSection>
<Flex alignItems={'center'} sx={{ gap: 1 }}>
<Flex alignItems={'center'} sx={{ gap: 1 }} flexWrap={'wrap'}>
<Text fontSize={14} color={theme.subText}>
{t`Current Price`}
</Text>
Expand All @@ -68,7 +68,7 @@ const RightSection = ({ position }: { position: ParsedPosition }) => {
{!revert ? position.token0Symbol : position.token1Symbol}
</Text>
<RevertIconWrapper onClick={() => setRevert(!revert)}>
<SwapIcon rotate={90} size={18} />
<SwapIcon size={18} />
</RevertIconWrapper>
</Flex>
</InfoSection>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Earns/PositionDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const PositionDetail = () => {
const { id, chainId } = useParams()
const { liquidityWidget, handleOpenZapInWidget, handleOpenZapOut } = useLiquidityWidget()
const { data: userPosition, isLoading } = useUserPositionsQuery(
{ addresses: account || '', positionId: id, chainIds: chainId },
{ addresses: account || '', positionId: id, chainIds: chainId || '', protocols: '', status: '', page: 1 },
{ skip: !account, pollingInterval: 15_000 },
)
const currentWalletAddress = useRef(account)
Expand Down
11 changes: 9 additions & 2 deletions src/pages/Earns/PositionDetail/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export const InfoSection = styled.div`
border-radius: 16px;
padding: 16px 24px;
border: 1px solid ${({ theme }) => theme.tabActive};
${({ theme }) => theme.mediaWidth.upToSmall`
padding: 16px;
`}
`

export const InfoSectionFirstFormat = styled(InfoSection)`
Expand Down Expand Up @@ -103,6 +107,7 @@ export const VerticalDivider = styled.div`
`

export const RevertIconWrapper = styled.div`
transform: rotate(90deg);
cursor: pointer;
:hover {
Expand Down Expand Up @@ -132,6 +137,7 @@ export const PositionAction = styled.button<{
padding: 10px 18px;
background-color: ${({ theme }) => theme.primary};
border: 1px solid ${({ theme }) => theme.primary};
color: ${({ theme }) => theme.black};
display: flex;
gap: 6px;
align-items: center;
Expand All @@ -144,8 +150,9 @@ export const PositionAction = styled.button<{
${({ theme, mobileAutoWidth }) =>
!mobileAutoWidth &&
theme.mediaWidth.upToSmall`
width: 100%;
`}
width: 100%;
justify-content: center;
`}
:hover {
filter: brightness(1.2);
Expand Down
45 changes: 30 additions & 15 deletions src/pages/Earns/UserPositions/Filter.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { t } from '@lingui/macro'
import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useMedia } from 'react-use'
import { Flex } from 'rebass'
import { PositionStatus } from 'services/zapEarn'
import { PositionQueryParams, PositionStatus } from 'services/zapEarn'

import Search from 'components/Search'
import useDebounce from 'hooks/useDebounce'
Expand All @@ -21,28 +22,42 @@ export default function Filter({
supportedChains,
supportedDexes,
filters,
onFilterChange,
updateFilters,
}: {
supportedChains: MenuOption[]
supportedDexes: MenuOption[]
filters: {
addresses: string
chainIds: string
protocols: string
status: string
q: string
}
onFilterChange: (key: string, value: string | number) => void
filters: PositionQueryParams
updateFilters: (key: keyof PositionQueryParams, value: string | number) => void
}) {
const [searchParams] = useSearchParams()
const [search, setSearch] = useState('')
const deboundedSearch = useDebounce(search, 300)
const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`)

useEffect(() => {
if (filters.q !== deboundedSearch) {
onFilterChange('q', deboundedSearch || '')
updateFilters('q', deboundedSearch || '')
}
}, [deboundedSearch, filters.q, onFilterChange])
}, [deboundedSearch, filters.q, updateFilters])

useEffect(() => {
if (searchParams.get('q') && !search) {
setSearch(searchParams.get('q') || '')
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

useEffect(() => {
if (
filters.protocols &&
!supportedDexes
.map(item => item.value)
.filter(Boolean)
.includes(filters.protocols)
) {
updateFilters('protocols', '')
}
}, [filters.protocols, supportedDexes, updateFilters])

return (
<Flex
Expand All @@ -57,21 +72,21 @@ export default function Filter({
mobileHalfWidth
value={filters.chainIds}
options={supportedChains.length ? supportedChains : [AllChainsOption]}
onChange={value => value !== filters.chainIds && onFilterChange('chainIds', value)}
onChange={value => value !== filters.chainIds && updateFilters('chainIds', value)}
/>
<DropdownMenu
alignLeft
mobileHalfWidth
value={filters.protocols}
options={supportedDexes.length ? supportedDexes : [AllProtocolsOption]}
onChange={value => value !== filters.protocols && onFilterChange('protocols', value)}
onChange={value => value !== filters.protocols && updateFilters('protocols', value)}
/>
<DropdownMenu
alignLeft
mobileFullWidth
value={filters.status}
options={POSITION_STATUS}
onChange={value => value !== filters.status && onFilterChange('status', value)}
onChange={value => value !== filters.status && updateFilters('status', value)}
/>
</Flex>
<Search
Expand Down
18 changes: 11 additions & 7 deletions src/pages/Earns/UserPositions/TableContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Loader from 'components/Loader'
import { MouseoverTooltipDesktopOnly } from 'components/Tooltip'
import NonfungiblePositionManagerABI from 'constants/abis/uniswapv3NftManagerContract.json'
import { APP_PATHS } from 'constants/index'
import { NETWORKS_INFO } from 'constants/networks'
import { useActiveWeb3React, useWeb3React } from 'hooks'
import useTheme from 'hooks/useTheme'
import { useWalletModalToggle } from 'state/application/hooks'
Expand All @@ -24,9 +25,9 @@ import { getReadingContract } from 'utils/getContract'
import { formatDisplayNumber } from 'utils/numbers'

import { CurrencyRoundedImage, CurrencySecondImage } from '../PoolExplorer/styles'
import ClaimFeeModal, { PositionToClaim, isNativeToken } from '../PositionDetail/ClaimFeeModal'
import { FeeInfo } from '../PositionDetail/LeftSection'
import { PositionAction as PositionActionBtn } from '../PositionDetail/styles'
import ClaimFeeModal, { PositionToClaim, isNativeToken } from '../components/ClaimFeeModal'
import { NFT_MANAGER_CONTRACT } from '../constants'
import { formatAprNumber } from '../utils'
import PriceRange from './PriceRange'
Expand Down Expand Up @@ -154,14 +155,16 @@ export default function TableContent({
const token0Address = position.pool.tokenAmounts[0]?.token.address
const token1Address = position.pool.tokenAmounts[1]?.token.address

const owner = await contract.ownerOf(position.id)

const results = await contract.callStatic.collect(
{
tokenId: id,
recipient: account,
recipient: owner,
amount0Max: maxUnit,
amount1Max: maxUnit,
},
{ from: account },
{ from: owner },
)
const balance0 = results.amount0.toString()
const balance1 = results.amount1.toString()
Expand Down Expand Up @@ -196,7 +199,7 @@ export default function TableContent({

setFeeInfoFromRpc(feeInfoFromRpcClone)
},
[account, feeInfoFromRpc, library, positions, setFeeInfoFromRpc],
[feeInfoFromRpc, library, positions, setFeeInfoFromRpc],
)

useEffect(() => {
Expand Down Expand Up @@ -283,6 +286,7 @@ export default function TableContent({

const isToken0Native = isNativeToken(token0Address, position.chainId as keyof typeof WETH)
const isToken1Native = isNativeToken(token1Address, position.chainId as keyof typeof WETH)
const nativeToken = NETWORKS_INFO[position.chainId as keyof typeof NETWORKS_INFO].nativeToken

return (
<PositionRow
Expand All @@ -297,7 +301,7 @@ export default function TableContent({
}
>
<PositionOverview>
<Flex alignItems={'center'} sx={{ gap: 2 }}>
<Flex alignItems={'center'} sx={{ gap: 2 }} flexWrap={'wrap'}>
<ImageContainer>
<CurrencyRoundedImage src={token0Logo} alt="" />
<CurrencySecondImage src={token1Logo} alt="" />
Expand Down Expand Up @@ -379,11 +383,11 @@ export default function TableContent({
<>
<Text>
{formatDisplayNumber(token0UnclaimedAmount, { significantDigits: 6 })}{' '}
{isToken0Native ? 'ETH' : token0Symbol}
{isToken0Native ? nativeToken.symbol : token0Symbol}
</Text>
<Text>
{formatDisplayNumber(token1UnclaimedAmount, { significantDigits: 6 })}{' '}
{isToken1Native ? 'ETH' : token1Symbol}
{isToken1Native ? nativeToken.symbol : token1Symbol}
</Text>
</>
}
Expand Down
Loading

0 comments on commit 5b399af

Please sign in to comment.